在撰写这篇文章之前,我对UserNotification框架进行了大量的研究,这在IOS 10中取代了UILocalNotification。我还学习了本教程,以了解有关这个新特性的一切:http://useyourloaf.com/blog/local-notifications-with-ios-10/。
今天,我在实现这些琐碎的通知时遇到了很多麻烦,而且由于这是最近的一个新特性,我找不到任何解决方案(尤其是在目标C中)。我现在有两个不同的通知,一个警报和一个徽章updtate。
警报问题
在将我的手机从IOS 10.1升级到10.2之前,我在Appdelegate上发出了一个警报,每当用户手动关闭应用程序时,该警报就会立即触发:
-(void)applicationWillTerminate:(UIApplication *)application {
NSLog(@"applicationWillTerminate");
// Notification terminate
[self registerTerminateNotification];
}
// Notification Background terminate
-(void) registerTerminateNotification {
// the center
UNUserNotificationCenter * notifCenter = [UNUserNotificationCenter currentNotificationCenter];
// Content
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.title = @"Stop";
content.body = @"Application closed";
content.sound = [UNNotificationSound defaultSound];
// Trigger
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
// Identifier
NSString *identifier = @"LocalNotificationTerminate";
// création de la requête
UNNotificationRequest *terminateRequest = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
// Ajout de la requête au center
[notifCenter addNotificationRequest:terminateRequest withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Error %@: %@",identifier,error);
}
}];
}在IOS 10.2之前,它运行得很好,当我手动关闭应用程序时,出现了一个警报。但是自从我更新到IOS 10.2之后,什么都没有出现,没有任何原因,我没有改变任何东西,我也看不见缺少什么。
的徽章问题
我也尝试过(这一次只在IOS 10.2中)在我的应用图标上实现徽章,这个图标工作得很好,直到我尝试删除它。以下是实现该功能的功能:
+(void) incrementBadgeIcon {
// only increment if application is in background
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground){
NSLog(@"increment badge");
// notif center
UNUserNotificationCenter *notifCenter = [UNUserNotificationCenter currentNotificationCenter];
// Content
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.badge = [NSNumber numberWithInt:1];
// Trigger
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
// Identifier
NSString *identifier = @"LocalNotificationIncrementBadge";
// request
UNNotificationRequest *incrementBadgeRequest = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
// Ajout de la requête au center
[notifCenter addNotificationRequest:incrementBadgeRequest withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Error %@: %@",identifier,error);
}
}];
}
}现在,它并没有像它的名称所建议的那样增加警徽号,而只是将警徽号设置为1。文档显示,如果您将content.badge设置为0,它就会删除它,但这是行不通的。我试过用其他数字,当我手动将它改为'2','3‘等.它会改变,但如果我将其设置为0,则无法工作。
此外,在我前面链接的教程中,还提到了几个函数,如getPendingNotificationRequests:completionHandler:和getDeliveredNotificationRequests:completionHandler:.。我注意到,当我在调用incrementBadgeIcon之后调用这些函数时,如果content.badge设置为'1‘、'2’等等.它出现在“挂起通知”列表中。但是,当我将其设置为0时,它不会出现在任何地方。我在Xcode中没有错误,没有警告,我的应用程序徽章仍然保留着。
有人知道我怎样才能修好这两个警报器吗?
提前感谢
PS:我也尝试使用removeAllPendingNotificationRequests和removeAllDeliveredNotifications,但都没有成功。
发布于 2016-12-19 03:24:03
那么,我终于设法使这两个警报起作用了。好像把这个问题贴在堆叠溢出上帮助我打开了过去几天困扰我的问题的思路(而且这些都是非常简单的答案,非常可耻)。
这是我的解决办法,如果有人进入这篇文章。
警报问题
对于应用程序关闭时应该显示的警报,例如,当应用程序在后台被用户杀死时,代码片段总体上是“正确的”。关键是,当applicationWillTerminate:触发appDelegate函数时,系统已经开始释放/拆卸应用程序的整个内存。因此,如果您的应用程序加载了许多视图,并且有许多数据可以释放,那么将通知添加到中心的线程就有足够的时间来完成它的任务。但是,如果应用程序只有很少的内存要处理,通知就永远不会添加到通知中心的队列中。
- (void)applicationWillTerminate:(UIApplication *)application {
NSLog(@"applicationWillTerminate");
// Notification terminate
[Utils closePollenNotification];
// Pause the termination thread
[NSThread sleepForTimeInterval:0.1f];
}因此,在我的例子中,我在创建通知后立即在applicationWillTerminate中添加了一个简单的睡眠,这为注册它提供了足够的时间。(注:我不知道这是否是一个好的练习,但它对我有效)。
徽章问题
显然,在更好地理解了苹果文档之后,将content.badge设置为0并不会删除以前的标记集。它只是告诉通知不要更新徽章。要删除它,只需调用sharedApplication函数:
//Reset badge icon
+(void) resetBadgeIcon {
NSLog(@"reset badge");
// remove basge
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
}太简单了。
希望这能帮上忙。
发布于 2017-01-02 19:27:59
关于警报:
当本地通知触发时,您的应用程序可能仍然处于前台,因此您需要实现委托方法,以便通知可以执行任何操作。例如,在委托中定义此方法将允许通知显示警报、发出声音并更新徽章:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert,.badge,.sound])
}关于徽章:
我已经注意到,创建一个UNMutableNotificationContent对象并只指定徽章值(作为一个NSNumber对象)对除0之外的所有徽章值都有效(也就是说,您不能以这种方式清除徽章)。我还没有找到任何文档来说明为什么0的行为会与任何其他值不同,特别是因为.badge属性被定义为NSNumber?,因此框架应该能够区分nil (无更改)和0 (清除徽章)。
我已经对此申请了雷达。
作为一项工作,我发现在title对象上设置带有NSNumber(value: 0) 值的属性会触发。如果title属性丢失,它将不会触发。
添加标题属性仍然不会向用户显示警告(更新:在iOS 11!中不再是这种情况),因此这是一种不需要调用UIApplication对象(通过UIApplication.shared.applicationIconBadgeNumber = 0)就可以静默地将徽章值更新为0的方法。
下面是我的示例项目中的全部代码;ViewController代码中有一个标记,显示插入title属性的位置解决了这个问题:
//
// AppDelegate.swift
// userNotificationZeroBadgeTest
//
// Created by Jeff Vautin on 1/3/17.
// Copyright © 2017 Jeff Vautin. All rights reserved.
//
import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { (success, error) -> Void in
print("Badge auth: \(success)")
}
// For handling Foreground notifications, this needs to be assigned before finishing this method
let vc = window?.rootViewController as! ViewController
let center = UNUserNotificationCenter.current()
center.delegate = vc
return true
}
}
//
// ViewController.swift
// userNotificationZeroBadgeTest
//
// Created by Jeff Vautin on 1/3/17.
// Copyright © 2017 Jeff Vautin. All rights reserved.
//
import UIKit
import UserNotifications
class ViewController: UIViewController, UNUserNotificationCenterDelegate {
@IBAction func start(_ sender: Any) {
// Reset badge directly (this always works)
UIApplication.shared.applicationIconBadgeNumber = 0
let center = UNUserNotificationCenter.current()
// Schedule badge value of 1 in 5 seconds
let notificationBadgeOneContent = UNMutableNotificationContent()
notificationBadgeOneContent.badge = NSNumber(value: 1)
let notificationBadgeOneTrigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 1*5, repeats: false)
let notificationBadgeOneRequest = UNNotificationRequest.init(identifier: "1", content: notificationBadgeOneContent, trigger: notificationBadgeOneTrigger)
center.add(notificationBadgeOneRequest)
// Schedule badge value of 2 in 10 seconds
let notificationBadgeTwoContent = UNMutableNotificationContent()
notificationBadgeTwoContent.badge = NSNumber(value: 2)
let notificationBadgeTwoTrigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 2*5, repeats: false)
let notificationBadgeTwoRequest = UNNotificationRequest.init(identifier: "2", content: notificationBadgeTwoContent, trigger: notificationBadgeTwoTrigger)
center.add(notificationBadgeTwoRequest)
// Schedule badge value of 3 in 15 seconds
let notificationBadgeThreeContent = UNMutableNotificationContent()
notificationBadgeThreeContent.badge = NSNumber(value: 3)
let notificationBadgeThreeTrigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 3*5, repeats: false)
let notificationBadgeThreeRequest = UNNotificationRequest.init(identifier: "3", content: notificationBadgeThreeContent, trigger: notificationBadgeThreeTrigger)
center.add(notificationBadgeThreeRequest)
// Schedule badge value of 4 in 20 seconds
let notificationBadgeFourContent = UNMutableNotificationContent()
notificationBadgeFourContent.badge = NSNumber(value: 4)
let notificationBadgeFourTrigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 4*5, repeats: false)
let notificationBadgeFourRequest = UNNotificationRequest.init(identifier: "4", content: notificationBadgeFourContent, trigger: notificationBadgeFourTrigger)
center.add(notificationBadgeFourRequest)
// Schedule badge value of 0 in 25 seconds
let notificationBadgeZeroContent = UNMutableNotificationContent()
// MARK: Uncommenting this line setting title property will cause notification to fire properly.
//notificationBadgeZeroContent.title = "Zero!"
notificationBadgeZeroContent.badge = NSNumber(value: 0)
let notificationBadgeZeroTrigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5*5, repeats: false)
let notificationBadgeZeroRequest = UNNotificationRequest.init(identifier: "0", content: notificationBadgeZeroContent, trigger: notificationBadgeZeroTrigger)
center.add(notificationBadgeZeroRequest)
}
@IBAction func listNotifications(_ sender: Any) {
let center = UNUserNotificationCenter.current()
center.getDeliveredNotifications() { (notificationArray) -> Void in
print("Delivered notifications: \(notificationArray)")
}
center.getPendingNotificationRequests() { (notificationArray) -> Void in
print("Pending notifications: \(notificationArray)")
}
}
// MARK: UNUserNotificationCenterDelegate
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("Received notification: \(notification)")
completionHandler([.alert,.badge,.sound])
}
}发布于 2017-02-08 01:02:40
此修补程序只适用于较早版本的iOS。仅用于向后兼容性.
这是针对OP描述的警徽问题的修复(但不是警报问题)。
步骤1:发送带有徽章=负1的通知
在您的UNMutableNotificationContent集中,content.badge = @-1而不是0。这有两个好处:
[UIApplication sharedApplication].applicationIconBadgeNumber = 0不同的是,它不会清除通知中心应用程序发出的警报。步骤2:实现UNUserNotificationCenterDelegate
您需要实现UNUserNotificationCenterDelegate并执行以下操作:
completionHandler(UNNotificationPresentationOptionBadge)。注意:我检查请求id,并调用默认的UNNotificationPresentationOptionNone,除非这是专门为清除徽章而设计的通知。在这两个更改之后,您可以再次使用本地通知清除徽章。
https://stackoverflow.com/questions/41210373
复制相似问题