Wie kann ich zuvor gelieferte Benachrichtigungen entfernen, wenn eine neue Benachrichtigung mit UNUserNotificationCenterDelegate in iOS 10 eingeht?

Diese Frage bezieht sich auf das neueUserNotifications Framework in iOS 10.

Ich habe eine App, die jede halbe Stunde nach dem Ausführen einer bestimmten Aktion in der App eine lokale Benachrichtigung plant, beginnend mit 1 Stunde.

Um den Sperrbildschirm oder das Benachrichtigungscenter eines Benutzers nicht zu überladen, soll immer nur eine Benachrichtigung angezeigt werden. Daher gibt es nur eine Benachrichtigung mit den neuesten relevanten Informationen. Mein Plan ist es, alle zugestellten Benachrichtigungen zu löschen, sobald eine neue Benachrichtigung angezeigt wird.

Es scheint, dass dies mit dem neuen @ möglich sein sollwillPresent Methode vonUNUserNotificationCenterDelegate, aber es verhält sich nicht so, wie ich es erwartet hätte.

Hier ist eine Funktion, die ich aufrufe, um alle Benachrichtigungen einzurichten, beginnend 1 Stunde nach dem Ereignis in der App, und eine Benachrichtigung alle halbe Stunde bis zum letzten um 23,5 Stunden nach dem Ereignis zu planen:

func updateNotifications() {

    for hour in 1...23 {
        scheduleNotification(withOffsetInHours: Double(hour))
        scheduleNotification(withOffsetInHours: Double(hour) + 0.5)
    }
}

Dies ist die Funktion, die die Benachrichtigungen basierend auf dem @ -Zeichen planmostRecentEventDate, die einDate anderswo einstellen:

func scheduleNotification(withOffsetInHours: Double) {

    // set up a Date for when the notification should fire
    let offsetInSeconds = 60 * 60 * withOffsetInHours
    let offsetFireDate = mostRecentEventDate.addingTimeInterval(offsetInSeconds)

    // set up the content of the notification
    let content = UNMutableNotificationContent()
    content.categoryIdentifier = "reminder"
    content.sound = UNNotificationSound.default()
    content.title = "Attention!"
    content.body = "It has been \(withOffsetInHours) hours since the most recent event."

    // set up the trigger
    let triggerDateComponents = Calendar.current.components([.year, .month, .day, .hour, .minute, .second], from: offsetFireDate)
    let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDateComponents, repeats: false)

    // set up the request
    let identifier = "reminder\(withOffsetInHours)"
    let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)

    // add the request for this notification
    UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in

        if error != nil {

            print(error)
        }
    })
}

In meinemUNUserNotificationCenterDelegate Ich habewillPresent Methode wie folgt eingerichtet:

func userNotificationCenter(_: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {

    print("will present...")

    UNUserNotificationCenter.current().removeAllDeliveredNotifications()

    withCompletionHandler([.alert,.sound])
}

Ich kenne daswillPresentie @ -Funktion wird aufgerufen, weil sie "Wird angezeigt ..." ausgibt, aber die vorhandenen Benachrichtigungen in der Benachrichtigungszentrale werden nicht gelöscht. Weiß jemand, warum das nicht funktioniert? Oder ob es eine Möglichkeit gibt, es so zu machen, wie ich es möchte?

BEARBEITEN Ich habe mir einen alternativen Ansatz ausgedacht, um das Gleiche zu erreichen, aber es scheint auch nicht zu funktionieren.

Meine Idee hier war, @ zu verwendwillPresent, um die eingehende geplante Benachrichtigung stumm zu schalten, während eine weitere Benachrichtigung sofort (ohne Auslöser) eingehen soll. Alle Benachrichtigungen, deren sofortiger Eingang geplant ist, haben dieselbe ID. Daher sollte die vorhandene Benachrichtigung mit dieser ID immer ersetzt werden, wie im Beispiel um 20:00 Uhr in dieses WWDC-Gespräch 2016 über das neue UserNotifications-Framework. Hier ist mein aktualisierteswillPresent Methode

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {

    let identifier = willPresent.request.identifier

    if identifier != "reminder" {

        let offsetInHoursString = identifier.replacingOccurrences(of: "reminder", with: "")

        let content = UNMutableNotificationContent()
        content.categoryIdentifier = "reminder"
        content.sound = UNNotificationSound.default()
        content.title = "Attention!"
        content.body = "It has been \(offsetInHoursString) hours since the most recent event."

        let identifier = "hydrationReminder"

        let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)

        center.add(request, withCompletionHandler: { (error) in

            if error != nil {

                print(error)
            }
        })

        withCompletionHandler([])

    } else {

        withCompletionHandler([.alert,.sound])
    }
}

BEARBEITEN Ich habe endlich gemerkt, dasswillPresent werdennu aufgerufen werden, wenn die App im Vordergrund ist, wie es ganz oben auf @ stediese Seit, also sollte keiner dieser Ansätze tatsächlich funktionieren. Ich dachtewillPresent wird jedes Mal aufgerufen, wenn eine Benachrichtigung empfangen wird. Zurück zum Reißbrett auf dieser "nur die neueste, relevanteste Benachrichtigung" Idee ...

UPDATE (Juli 2018): Mit der Einführung von gruppierten Benachrichtigungen in iOS 12 erscheint die Aktualisierung einer älteren Benachrichtigung (mit dem Ziel, die Unordnung der Benachrichtigungen zu verringern) weniger relevant. Ich möchte immer noch in der Lage sein, das Auftreten von Unordnung zu minimieren, und es scheint, dass es eine Feature-Parität zwischen Remote-Push-Benachrichtigungen, die nachträglich aktualisiert werden können, und lokalen Benachrichtigungen, die später nicht aktualisiert werden können, geben sollte. Da Apple jedoch gruppierte Benachrichtigungen eingeführt hat, ist es weniger wahrscheinlich, dass alte lokale Benachrichtigungen aktualisiert werden können, sodass Apps nur neue senden und diese zusammen mit vorhandenen Benachrichtigungen gruppieren können.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage