我在我的应用程序中使用UserNotification框架并发送本地通知(不是推送通知),我想将徽章设置为收到的通知数量,所以我做的是将收到的通知数设置为用户默认值然后我尝试过将值分配给徽章以获取徽章编号,但徽章编号不会增加.这是我的代码
设置接收通知的值
center.getDeliverednotifications { notification in
UserDefaults.standard.set(notification.count,forKey: Constants.NOTIFICATION_COUNT)
print("notification.count \(notification.count)")
print(".count noti \(UserDefaults.standard.integer(forKey: Constants.NOTIFICATION_COUNT))")
}
这准确地打印了收到的通知数量,当我决定将其设置为我的徽章时,它只显示1
content.badge = NSNumber(value: UserDefaults.standard.integer(forKey: Constants.NOTIFICATION_COUNT))
我不知道为什么价值不会每次都增加.任何帮助,将不胜感激.
或者,如果可以在应用程序的任何位置始终更新徽章.
解决方法
像这样发送本地通知:
func sendNotification(title: String,subtitle: String,body: String,timeInterval: TimeInterval) {
let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests(completionHandler: { pendingNotificationRequests in
//Use the main thread since we want to access UIApplication.shared.applicationIconBadgeNumber
dispatchQueue.main.sync {
//Create the new content
let content = UNMutableNotificationContent()
content.title = title
content.subtitle = subtitle
content.body = body
//Let's store the firing date of this notification in content.userInfo
let firingDate = Date().timeIntervalSince1970 + timeInterval
content.userInfo = ["timeInterval": firingDate]
//get the count of pending notification that will be fired earlier than this one
let earlierNotificationsCount: Int = pendingNotificationRequests.filter { request in
let userInfo = request.content.userInfo
if let time = userInfo["timeInterval"] as? Double {
if time < firingDate {
return true
} else {
//Here we update the notofication that have been created earlier,BUT have a later firing date
let newContent: UNMutableNotificationContent = request.content.mutablecopy() as! UNMutableNotificationContent
newContent.badge = (Int(truncating: request.content.badge ?? 0) + 1) as NSNumber
let newRequest: UNNotificationRequest =
UNNotificationRequest(identifier: request.identifier,content: newContent,trigger: request.trigger)
center.add(newRequest,withCompletionHandler: { (error) in
// Handle error
})
return false
}
}
return false
}.count
//Set the badge
content.badge = NSNumber(integerLiteral: UIApplication.shared.applicationIconBadgeNumber + earlierNotificationsCount + 1)
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval,repeats: false)
let requestIdentifier = UUID().uuidString //You probably want to save these request identifiers if you want to remove the corresponding notifications later
let request = UNNotificationRequest(identifier: requestIdentifier,content: content,trigger: trigger)
center.add(request,withCompletionHandler: { (error) in
// Handle error
})
}
})
}
(您可能需要保存请求的标识符(如果您想更新它们,可以在用户默认值或核心数据中保存,甚至可以通过removePendingNotificationRequests(withIdentifiers:)取消它们)
您可以像这样调用上面的函数:
sendNotification(title: "Meeting Reminder",subtitle: "Staff Meeting in 20 minutes",body: "Don't forget to bring coffee.",timeInterval: 10)
将您的视图控制器声明为UNUserNotificationCenterDelegate:
class ViewController: UIViewController,UNUserNotificationCenterDelegate {
override func viewDidLoad() {
super.viewDidLoad()
UNUserNotificationCenter.current().delegate = self
}
//...
}
要处理与通知的互动,请更新应用的徽章以及即将发布的通知的徽章:
func userNotificationCenter(_ center: UNUserNotificationCenter,didReceive response: UNNotificationResponse,withCompletionHandler completionHandler: @escaping () -> Void) {
//UI updates are done in the main thread
dispatchQueue.main.async {
UIApplication.shared.applicationIconBadgeNumber -= 1
}
let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests(completionHandler: {requests in
//Update only the notifications that have userInfo["timeInterval"] set
let newRequests: [UNNotificationRequest] =
requests
.filter{ rq in
return rq.content.userInfo["timeInterval"] is Double?
}
.map { request in
let newContent: UNMutableNotificationContent = request.content.mutablecopy() as! UNMutableNotificationContent
newContent.badge = (Int(truncating: request.content.badge ?? 0) - 1) as NSNumber
let newRequest: UNNotificationRequest =
UNNotificationRequest(identifier: request.identifier,trigger: request.trigger)
return newRequest
}
newRequests.forEach { center.add($0,withCompletionHandler: { (error) in
// Handle error
})
}
})
completionHandler()
}
这会在通知与点击进行交互时通过减少应用徽章来更新应用徽章.此外,它还会更新待处理通知的内容徽章.添加具有相同标识符的通知请求只会更新待处理通知.
要在前台接收通知,并在未与通知交互时增加应用徽章图标,请执行以下操作:
func userNotificationCenter(_ center: UNUserNotificationCenter,willPresent notification: UNNotification,withCompletionHandler completionHandler: @escaping (UNNotificationPresentationoptions) -> Void) {
dispatchQueue.main.async {
UIApplication.shared.applicationIconBadgeNumber += 1
}
completionHandler([.alert,.sound])
}
这是一些GIF:
> 1st:接收本地通知会增加应用徽章.而与通知进行交互会减少应用徽章.
> 2nd:应用程序被杀时接收本地通知(我在此使用了15秒的触发timeInterval).
> 3rd:在前台接收通知会增加应用程序徽章,除非用户与之交互.
我的测试项目中使用的完整类看起来像这样:
import UIKit
import UserNotifications
class ViewController: UIViewController,UNUserNotificationCenterDelegate {
var bit = true
@IBAction func send(_ sender: UIButton) {
let time: TimeInterval = bit ? 8 : 4
bit.toggle()
sendNotification(title: "Meeting Reminder",timeInterval: time)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view,typically from a nib.
UNUserNotificationCenter.current().delegate = self
}
func sendNotification(title: String,timeInterval: TimeInterval) {
let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests(completionHandler: { pendingNotificationRequests in
dispatchQueue.main.sync {
let content = UNMutableNotificationContent()
content.title = title
content.subtitle = subtitle
content.body = body
let firingDate = Date().timeIntervalSince1970 + timeInterval
content.userInfo = ["timeInterval": firingDate]
let earlierNotificationsCount: Int = pendingNotificationRequests.filter { request in
let userInfo = request.content.userInfo
if let time = userInfo["timeInterval"] as? Double {
if time < firingDate {
return true
} else {
let newContent: UNMutableNotificationContent = request.content.mutablecopy() as! UNMutableNotificationContent
newContent.badge = (Int(truncating: request.content.badge ?? 0) + 1) as NSNumber
let newRequest: UNNotificationRequest =
UNNotificationRequest(identifier: request.identifier,trigger: request.trigger)
center.add(newRequest,withCompletionHandler: { (error) in
// Handle error
})
return false
}
}
return false
}.count
content.badge = NSNumber(integerLiteral: UIApplication.shared.applicationIconBadgeNumber + earlierNotificationsCount + 1)
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval,repeats: false)
let requestIdentifier = UUID().uuidString //You probably want to save these request identifiers if you want to remove the corresponding notifications later
let request = UNNotificationRequest(identifier: requestIdentifier,trigger: trigger)
center.add(request,withCompletionHandler: { (error) in
// Handle error
})
}
})
}
func userNotificationCenter(_ center: UNUserNotificationCenter,withCompletionHandler completionHandler: @escaping (UNNotificationPresentationoptions) -> Void) {
dispatchQueue.main.async {
UIApplication.shared.applicationIconBadgeNumber += 1
}
completionHandler([.alert,.sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,withCompletionHandler completionHandler: @escaping () -> Void) {
dispatchQueue.main.async {
UIApplication.shared.applicationIconBadgeNumber -= 1
}
let center = UNUserNotificationCenter.current()
center.getPendingNotificationRequests(completionHandler: {requests in
let newRequests: [UNNotificationRequest] =
requests
.filter{ rq in
return rq.content.userInfo["timeInterval"] is Double?
}
.map { request in
let newContent: UNMutableNotificationContent = request.content.mutablecopy() as! UNMutableNotificationContent
newContent.badge = (Int(truncating: request.content.badge ?? 0) - 1) as NSNumber
let newRequest: UNNotificationRequest =
UNNotificationRequest(identifier: request.identifier,trigger: request.trigger)
return newRequest
}
newRequests.forEach { center.add($0,withCompletionHandler: { (error) in
// Handle error
})
}
})
completionHandler()
}
}