无法更新本地定时通知内容
Unable to update local scheduled notification content
在一次 WWDC 会议中,我获得了用于更新现有通知的代码片段。我认为这行不通。正在尝试更新通知内容。
首先,我请求来自 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.
选择第二个 "delete first" 选项。注意到调用 removePendingNotificationRequests
并在之后安排,仍然给我旧的通知版本。我不得不在调用 removePendingNotificationRequests
和 center.add(request)
之间添加 1 秒的延迟。
已将 Chris 的回答标记为已接受,但欢迎分享更好的选择。
问题是您没有修改现有通知,而是添加了一个具有重复标识符的新通知。
让我们先解决重复问题,这个重复通知没有出现的原因是标识符不是唯一的。来自 docs:
(if identifier is not unique, notifications are not delivered).
你有两个选择。您可以 1) 修改现有通知,或 2) 删除它并添加新通知。
对于 1,您已经有了请求,而不是从中提取触发器和标识符,只需将 request.content 替换为更新后的 notificationContent。
对于 2,您只需要在添加之前添加一行:
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [request!.identifier])
在我请求允许通知之后:
我直接从我的 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)")
}
})
}
}
}
在上面的代码片段中:删除 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])
}
}
在一次 WWDC 会议中,我获得了用于更新现有通知的代码片段。我认为这行不通。正在尝试更新通知内容。
首先,我请求来自 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.
选择第二个 "delete first" 选项。注意到调用 removePendingNotificationRequests
并在之后安排,仍然给我旧的通知版本。我不得不在调用 removePendingNotificationRequests
和 center.add(request)
之间添加 1 秒的延迟。
已将 Chris 的回答标记为已接受,但欢迎分享更好的选择。
问题是您没有修改现有通知,而是添加了一个具有重复标识符的新通知。
让我们先解决重复问题,这个重复通知没有出现的原因是标识符不是唯一的。来自 docs:
(if identifier is not unique, notifications are not delivered).
你有两个选择。您可以 1) 修改现有通知,或 2) 删除它并添加新通知。
对于 1,您已经有了请求,而不是从中提取触发器和标识符,只需将 request.content 替换为更新后的 notificationContent。
对于 2,您只需要在添加之前添加一行:
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [request!.identifier])
在我请求允许通知之后:
我直接从我的 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)")
}
})
}
}
}
在上面的代码片段中:删除 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])
}
}