无法更新本地预定通知内容

Posted

技术标签:

【中文标题】无法更新本地预定通知内容【英文标题】:Unable to update local scheduled notification content 【发布时间】:2017-07-11 11:56:20 【问题描述】:

在一次 WWDC 会议中,我获得了用于更新现有通知的代码 sn-p。我不认为它有效。正在尝试更新通知内容。

首先,我向UNUserNotificationCenter 请求待处理通知,这始终有效。然后我正在创建新的请求以使用现有的唯一标识符更新通知。

有 1 个新变量 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)")
    
)

我无法捕捉到错误。问题是通知内容body没有改变。

更新。

我还尝试使用不同的重复间隔更改触发器。它不起作用,通知会以与创建时相同的原始间隔重复。

更新 2。

阅读 Chris 的回答,尝试使用第一个选项。

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.
        
    
)

如您所见,我无法修改原始请求。

更新 3。

已经选择了第二个“先删除”选项。注意到调用removePendingNotificationRequests 并安排之后,仍然给我旧的通知版本。我不得不在调用removePendingNotificationRequestscenter.add(request) 之间增加1 秒的延迟。

已将 Chris 的回答标记为已接受,但请随时分享更好的选择。

【问题讨论】:

content 的类型是什么?你能打印出来并确保它是你所期望的吗? 内容类型为字符串。 FWIW 这是一个令人困惑的名字。不要试图通过给内容不同的名称来区分notificationContent.bodycontent。只需将其写为notificationContent.body = body,因为加班时您可能会遇到我刚刚遇到的确切困惑。左边是另一个的属性,右边是一个局部变量——足以让其他人知道不同之处,也知道相似之处。但是您可以再次打印并查看正文/标题是否是您所期望的吗?让我知道结果。否则,到目前为止,您的代码看起来还不错。我还粘贴了我自己的 Xcode 来试一试。 你一定是在代码的其他地方做错了,否则你的字符串又不正确了。我刚刚用一个非常相似的代码进行了验证。我对 identifier 以外的所有内容进行了更改,并更新了之前的通知。为此,您无需删除待处理的通知。只需将新的 NotificationRequest 添加到 NotificationsCenter 即可。我强烈建议您查看此answer 并下载示例项目。这是一个非常非常好的示例项目 使用您当前的解决方案将最后一行 request.content = notificationContent to let updateRequest = UNNotificationRequest(identifier: notificationIdentifier, content: notificationContent, trigger: newTrigger)UNUserNotificationCenter.current().add(updateRequest, withCompletionHandler: (error) in print("successfully updated") if error != nil print("???? Couldn't update notification \(error!.localizedDescription)") 更改。基本上抢 【参考方案1】:

问题在于您没有修改现有通知,而是添加了具有重复标识符的新通知。

让我们首先解决重复问题,这个重复通知没有显示的原因是标识符不是唯一的。来自docs:

(如果标识符不是唯一的,则不会传递通知)。

你有两个选择。您可以 1) 修改现有通知,或 2) 将其删除并添加新通知。

对于 1,您已经有了请求,而不是从中提取触发器和标识符,只需将 request.content 替换为您更新的 notificationContent。

对于 2,您只需要在添加之前添加一行:

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

【讨论】:

您不需要删除它。见here。不知道你的意思是你不必拉出触发器/标识符。也许如果你添加一些代码会更清楚。尽管您提供的报价让我感到困惑,因为有多个具有相同标识符的通知,但会重写前一个。见here。想... 我是说他可以接受他现有的请求并更新内容。相反,他正在使用旧触发器的详细信息执行新触发器,并使用旧通知的标识符执行新通知。 嗨@ChrisAllwein,您的回答确实有道理,但是我无法真正更新请求,因为它的属性是只读的。我已经用您在选项 1 中建议的代码更新了我的问题。 无需删除待处理的通知。我刚刚验证了这一点。但你对他是如何混淆自己的看法是对的。【参考方案2】:

在我请求允许通知之后:

我直接从我的viewDidLoad 触发了一个通知,但随后也触发了另一个具有相同标识符的通知。最后,updatedBody/updatedTitle 出现。

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()
    

我的更新功能

    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)")
                
            )
        

    


在上面的 sn-p 中:删除 center.removeAllPendingNotificationRequests() 不会有任何区别。我仍然会收到更新的通知。

用于处理传入通知

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])

    

【讨论】:

仅供参考,我正在处理重复通知,当然删除和创建新通知会解决这个问题,但我不想删除它,所以重复循环不会停止。 @borisy 然后请在您的问题中更新并明确说明 我不会关注这个,因为我认为重复的truefalse 在这里没有什么不同。公平地说,我的问题确实已经说明了这一点。 @borisy 我真的很困惑你想要什么:“所以重复循环不会刹车”这是什么意思?!您的意思是如果您的间隔设置为 60 秒,而您将其更改为 90 秒,则间隔时间仍保持在 60 秒? 假设我们计划从星期一开始每周重复一次通知。然后周五通知的内容需要更新。更新过程通知必须在下周一触发。但是,如果我决定删除通知并创建新通知而不是更新现有通知,它将在下周五触发。

以上是关于无法更新本地预定通知内容的主要内容,如果未能解决你的问题,请参考以下文章

UNNotificationServiceExtension 偶尔无法更新通知

本地通知颤动

Android开发本地及网络Mp3音乐播放器(十九)通知媒体库更新刚下载的MP3

CloudKit 不发送更新通知

Android 在电话簿更新时通知(内容观察者)

macOS更新细节:“--ignore”命令失效 无法隐藏更新通知