Unable to update local scheduled notification content

早过忘川 提交于 2019-12-22 06:35:22

问题


In one of the WWDC sessions I got code snippet for updating existing notifications. I don't think it works. Trying to update notification content.

First I request pending notifications from UNUserNotificationCenter which always works. Then I am creating new request to update notification with existing unique identifier.

There's 1 new variable content: String.

// Got at least one pending notification.
let triggerCopy = request!.trigger as! UNTimeIntervalNotificationTrigger
let interval = triggerCopy.timeInterval
let newTrigger = UNTimeIntervalNotificationTrigger(timeInterval: interval, repeats: true)

// Update notificaion conent.
let notificationContent = UNMutableNotificationContent()
notificationContent.title = NSString.localizedUserNotificationString(forKey: "Existing Title", arguments: nil)
notificationContent.body = content
let updateRequest = UNNotificationRequest(identifier: request!.identifier, content: notificationContent, trigger: newTrigger)
UNUserNotificationCenter.current().add(updateRequest, withCompletionHandler: { (error) in
    if error != nil {
        print("🚫 Couldn't update notification \(error!.localizedDescription)")
    }
})

I am unable to catch error. The problem is that notification content body doesn't change.

Update.

I also tried to change trigger with different repeat interval. It doesn't work, notification is repeated with the same original interval it was created with.

Update 2.

Read Chris' answer, trying to go with first option.

let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests(completionHandler: { (requests) in
    for request in requests {
        if request.identifier == notificationIdentifier {
            // Got at least one pending notification,
            // update its content.
            let notificationContent = UNMutableNotificationContent()
            notificationContent.title = NSString.localizedUserNotificationString(forKey: "new title", arguments: nil)
            notificationContent.body = "new body"
            request.content = notificationContent // ⛔️ request.content is read only.
        }
    }
})

As you can see I can't modify original request.

Update 3.

Had go with second "delete first" option. Noticed that calling removePendingNotificationRequests and schedule after, still gives me old notification version. I had to add 1 second delay between calling removePendingNotificationRequests and center.add(request).

Marked Chris' answer as accepted but feel free to share better option.


回答1:


The problem is that you're not modifying the existing notification, and instead adding a new notification with a duplicate identifier.

Let's tackle the duplicate issue first, the reason this duplicate notification doesn't show up is because the identifier isn't unique. From the docs:

(if identifier is not unique, notifications are not delivered).

You have two options. You can 1) modify the existing Notification, or 2) remove it and add the new one.

For 1, you already have the request, instead of pulling the trigger and identifier out of it, just replace request.content with your updated notificationContent.

For 2, you would just need to add a line before your Add:

UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [request!.identifier])



回答2:


After I've requested to Allow Notifications:

I trigger a notification right from my viewDidLoad but then also trigger another one with the same identifier. At the end the the updatedBody/updatedTitle show up.

import UIKit
import UserNotifications

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let content = UNMutableNotificationContent()
        content.title = "Scheduled Task"
        content.body = "dumbBody"
        content.badge = 1
        content.sound = UNNotificationSound.default()
        content.categoryIdentifier = "alertCategory"

        UNUserNotificationCenter.current().delegate = self

        //Setting time for notification trigger
        let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 3.0, repeats: false)
        let request = UNNotificationRequest(identifier:"myIdentifier", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request, withCompletionHandler: {_ in print(" was registered")})

        updateNotification()
    }

My update function

    func updateNotification(){

        let center = UNUserNotificationCenter.current()
        var request : UNNotificationRequest?

        center.getPendingNotificationRequests{ notifications in
            for notificationRequest in notifications{
                if notificationRequest.identifier == "myIdentifier"{
                    request = notificationRequest
                    center.removeAllPendingNotificationRequests() // Removing this line or keeping it makes NO difference
                }

            }

            let newTrigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5.0, repeats: false)

            // Update notificaion conent.
            let notificationContent = UNMutableNotificationContent()
            notificationContent.title = "UpdatedTitle"

            notificationContent.body = "updatedBody"
            let updateRequest = UNNotificationRequest(identifier: request!.identifier, content: notificationContent, trigger: newTrigger)
            UNUserNotificationCenter.current().add(updateRequest, withCompletionHandler: { (error) in
                print("successfully updated")
                if error != nil {
                    print("🚫 Couldn't update notification \(error!.localizedDescription)")
                }
            })
        }

    }

}

In the above snippet: Removing center.removeAllPendingNotificationRequests() would make no difference. Still I would receive the updatedNotification.

For handling incoming notifications

extension ViewController:UNUserNotificationCenterDelegate{      

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    print("original identifier was : \(response.notification.request.identifier)")
    print("original body was : \(response.notification.request.content.body)")
    print("Tapped in notification")

    switch response.actionIdentifier {
    default:
        print("some action was clicked")
    }
}

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

        print("Notification being triggered")
        completionHandler( [.alert,.sound,.badge])

    }
}


来源:https://stackoverflow.com/questions/45033911/unable-to-update-local-scheduled-notification-content

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!