UNUserNotificationCenter 确实收到了响应,但从未调用完成处理程序 iOS10、swift 2.3
UNUserNotificationCenter did receive response with completion handler is never called iOS10, swift 2.3
我正在 iOS10 中安排新通知,如下所示:
func scheduleNotification (event : Meeting, todaysBadgeCounter: Int) {
if #available(iOS 10.0, *) {
let minutesBefore = 10
//interval in seconds from current point in time to notification
let interval : NSTimeInterval = NSTimeInterval(secondsFromNowTo(event.startTime.dateByAddingTimeInterval(-minutesBefore * 60)))
//only schedule in the future
if(interval > 0){
let category = NotificationsController.notificationCategory
let center = NotificationsController.notificationCenter
center.setNotificationCategories([category])
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationStringForKey(event.title, arguments: nil)
if(minutesBefore <= 1){
content.body = NSString.localizedUserNotificationStringForKey("IOS10: Your \(event.title) is about to start", arguments: nil)
}else{
content.body = NSString.localizedUserNotificationStringForKey("IOS10: You have \(event.title) in \(Int(minutesBefore)) minutes", arguments: nil)
}
content.sound = UNNotificationSound.defaultSound()
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
let identifier = NSString.localizedUserNotificationStringForKey("sampleRequest\(event.UUID)", arguments: nil)
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
//setting the delegate
center.delegate = self
center.addNotificationRequest(request, withCompletionHandler: { (error) in
// handle the error if needed
log.error(error?.localizedDescription)
print("SCHEDULING >=iOS10:", event.title, ", interval:", interval)
})
}
//return category
@available(iOS 10.0, *)
class var notificationCategory : UNNotificationCategory {
struct Static {
static let callNow = UNNotificationAction(identifier: NotificationActions.callNow.rawValue, title: "Call now", options: [])
static let clear = UNNotificationAction(identifier: NotificationActions.clear.rawValue, title: "Clear", options: [])
static let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])
}
return Static.category
}
我可以安排通知,并在合适的时间接收本地通知。 但是: 我根据教程使用的委托方法从未执行过,但是每次我点击通知时都会执行 didReceiveLocalNotification:
extension NotificationsController: UNUserNotificationCenterDelegate {
@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
print("IOS10 delivered")
// Response has actionIdentifier, userText, Notification (which has Request, which has Trigger and Content)
switch response.actionIdentifier {
case NotificationActions.NotifyBefore.rawValue:
print("notify")
break
case NotificationActions.callNow.rawValue:
print("callNow")
break
case NotificationActions.clear.rawValue:
print("clear")
default: break
}
}
@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
// Delivers a notification to an app running in the foreground.
print("IOS10 delivered 2222")
}
}
didReceiveLocalNotification 是否已弃用?如何让这些方法被调用?
更新:
我根据此处的一些建议更新了我的代码,即:
- 我添加了 UNUserNotificationCenter.delegate 到 applicationDidFinishLaunchingWithOptions 的分配。
- 我还尝试将这些方法(委托方法)从 NotificationsController.swift class 的扩展中移出,并将此 class 设置为 UNUserNotificationCenterDelegate。对我也不起作用。
您使用的函数签名不正确
swift 中正确的函数签名是:
func userNotificationCenter(UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {
//your code here
}
和
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
//your code here
}
根据 UNUserNotificationCenterDelegate docs:
Important
You must assign your delegate object to the UNUserNotificationCenter
object no later before your app finishes launching. For example, in an
iOS app, you must assign it in the applicationWillFinishLaunching(:)
or applicationDidFinishLaunching(:) method.
所以,这可能是设置通知中心代理太晚的问题。
确保您的 AppDelegate 实施 UNUserNotificationCenterDelegate
协议。
对于Swift
let center = UNUserNotificationCenter.current()
center.delegate = self
对于Objective-c
//set delegate to self
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
将委托分配给自己将触发以下方法。
// App in foreground
private func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
}
//On Action click
private func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
print("didReceive")
}
请求标识符不是通知类别。
只需添加这一行:
content.categoryIdentifier = identifier
更新:
只是做了一个简单的应用程序。似乎一切正常:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
self.registerCategory()
self.scheduleNotification(event: "test", interval: 3)
self.scheduleNotification(event: "test2", interval: 5)
}
}
return true
}
func registerCategory() -> Void{
let callNow = UNNotificationAction(identifier: "call", title: "Call now", options: [])
let clear = UNNotificationAction(identifier: "clear", title: "Clear", options: [])
let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])
let center = UNUserNotificationCenter.current()
center.setNotificationCategories([category])
}
func scheduleNotification (event : String, interval: TimeInterval) {
let content = UNMutableNotificationContent()
content.title = event
content.body = "body"
content.categoryIdentifier = "CALLINNOTIFICATION"
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
let identifier = "id_"+event
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: { (error) in
})
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
print("didReceive")
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
completionHandler([.badge, .alert, .sound])
}
}
更新 2:在 Swift 2.3
中重写
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func applicationDidFinishLaunching(application: UIApplication) {
UNUserNotificationCenter.currentNotificationCenter().delegate = self
UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptions([.Badge, .Sound, .Alert]) { (granted, error) in
if granted {
self.registerCategory()
self.scheduleNotification("test", interval: 3)
self.scheduleNotification("test2", interval: 5)
}
}
}
func registerCategory() -> Void{
let callNow = UNNotificationAction(identifier: "call", title: "Call now", options: [])
let clear = UNNotificationAction(identifier: "clear", title: "Clear", options: [])
let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])
let center = UNUserNotificationCenter.currentNotificationCenter()
center.setNotificationCategories([category])
}
func scheduleNotification(event : String, interval: NSTimeInterval) {
let content = UNMutableNotificationContent()
content.title = event
content.body = "body"
content.categoryIdentifier = "CALLINNOTIFICATION"
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
let identifier = "id_"+event
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
let center = UNUserNotificationCenter.currentNotificationCenter()
center.addNotificationRequest(request) { (error) in
}
}
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
completionHandler([.Badge, .Alert, .Sound])
}
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
print("didReceive")
completionHandler()
}
}
我找到了这个问题的答案。当 运行 app on Xcode 8 with Swift 2.3 和最小部署目标为 iOS 9.3.
时调用下面的委托方法
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)
在swift3.0中使用,
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void)
使用 belwo 委托方法 Swift 2.3:
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)
为Swift3.0
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("** willPresent")
completionHandler([.badge, .alert, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
print("** didReceive")
completionHandler()
}
文档说要在 applicationWillFinishLaunching(:) 或 applicationDidFinishLaunching(:) 中设置委托。所以在 AppDelegate 中包含以下代码:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
}
设置此委托后,将调用以下 willPresent 函数。
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
completionHandler([.alert, .sound])
}
检查以确保只有您的 AppDelegate 被设置为 UNUserNotificationCenter Delegate。
你在使用...
UNUserNotificationCenter.current().delegate = self
...不止一次?我试图通过更改每个视图控制器中的委托并让每个视图控制器都使用此函数来捕获所有视图控制器中具有不同结果的通知:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
// code
}
我的问题是我还没有实现它们的功能,所以我的 AppDelegate 中的原始 userNotificationCenter 函数 "didReceive" 没有被调用。这可能就是您的电话未被调用的原因。
我遇到了同样的问题。
正在替换
[UNCalendarNotificationTrigger triggerWithDateMatchingComponents:dateComponents repeats:NO];
有
[UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];
对我有帮助。当然这还有其他作用,但至少现在可以用了
我正在 iOS10 中安排新通知,如下所示:
func scheduleNotification (event : Meeting, todaysBadgeCounter: Int) {
if #available(iOS 10.0, *) {
let minutesBefore = 10
//interval in seconds from current point in time to notification
let interval : NSTimeInterval = NSTimeInterval(secondsFromNowTo(event.startTime.dateByAddingTimeInterval(-minutesBefore * 60)))
//only schedule in the future
if(interval > 0){
let category = NotificationsController.notificationCategory
let center = NotificationsController.notificationCenter
center.setNotificationCategories([category])
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationStringForKey(event.title, arguments: nil)
if(minutesBefore <= 1){
content.body = NSString.localizedUserNotificationStringForKey("IOS10: Your \(event.title) is about to start", arguments: nil)
}else{
content.body = NSString.localizedUserNotificationStringForKey("IOS10: You have \(event.title) in \(Int(minutesBefore)) minutes", arguments: nil)
}
content.sound = UNNotificationSound.defaultSound()
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
let identifier = NSString.localizedUserNotificationStringForKey("sampleRequest\(event.UUID)", arguments: nil)
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
//setting the delegate
center.delegate = self
center.addNotificationRequest(request, withCompletionHandler: { (error) in
// handle the error if needed
log.error(error?.localizedDescription)
print("SCHEDULING >=iOS10:", event.title, ", interval:", interval)
})
}
//return category
@available(iOS 10.0, *)
class var notificationCategory : UNNotificationCategory {
struct Static {
static let callNow = UNNotificationAction(identifier: NotificationActions.callNow.rawValue, title: "Call now", options: [])
static let clear = UNNotificationAction(identifier: NotificationActions.clear.rawValue, title: "Clear", options: [])
static let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])
}
return Static.category
}
我可以安排通知,并在合适的时间接收本地通知。 但是: 我根据教程使用的委托方法从未执行过,但是每次我点击通知时都会执行 didReceiveLocalNotification:
extension NotificationsController: UNUserNotificationCenterDelegate {
@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
print("IOS10 delivered")
// Response has actionIdentifier, userText, Notification (which has Request, which has Trigger and Content)
switch response.actionIdentifier {
case NotificationActions.NotifyBefore.rawValue:
print("notify")
break
case NotificationActions.callNow.rawValue:
print("callNow")
break
case NotificationActions.clear.rawValue:
print("clear")
default: break
}
}
@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
// Delivers a notification to an app running in the foreground.
print("IOS10 delivered 2222")
}
}
didReceiveLocalNotification 是否已弃用?如何让这些方法被调用?
更新:
我根据此处的一些建议更新了我的代码,即:
- 我添加了 UNUserNotificationCenter.delegate 到 applicationDidFinishLaunchingWithOptions 的分配。
- 我还尝试将这些方法(委托方法)从 NotificationsController.swift class 的扩展中移出,并将此 class 设置为 UNUserNotificationCenterDelegate。对我也不起作用。
您使用的函数签名不正确
swift 中正确的函数签名是:
func userNotificationCenter(UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {
//your code here
}
和
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
//your code here
}
根据 UNUserNotificationCenterDelegate docs:
Important
You must assign your delegate object to the UNUserNotificationCenter object no later before your app finishes launching. For example, in an iOS app, you must assign it in the applicationWillFinishLaunching(:) or applicationDidFinishLaunching(:) method.
所以,这可能是设置通知中心代理太晚的问题。
确保您的 AppDelegate 实施 UNUserNotificationCenterDelegate
协议。
对于Swift
let center = UNUserNotificationCenter.current()
center.delegate = self
对于Objective-c
//set delegate to self
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
将委托分配给自己将触发以下方法。
// App in foreground
private func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
}
//On Action click
private func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
print("didReceive")
}
请求标识符不是通知类别。
只需添加这一行:
content.categoryIdentifier = identifier
更新: 只是做了一个简单的应用程序。似乎一切正常:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
self.registerCategory()
self.scheduleNotification(event: "test", interval: 3)
self.scheduleNotification(event: "test2", interval: 5)
}
}
return true
}
func registerCategory() -> Void{
let callNow = UNNotificationAction(identifier: "call", title: "Call now", options: [])
let clear = UNNotificationAction(identifier: "clear", title: "Clear", options: [])
let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])
let center = UNUserNotificationCenter.current()
center.setNotificationCategories([category])
}
func scheduleNotification (event : String, interval: TimeInterval) {
let content = UNMutableNotificationContent()
content.title = event
content.body = "body"
content.categoryIdentifier = "CALLINNOTIFICATION"
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
let identifier = "id_"+event
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: { (error) in
})
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
print("didReceive")
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
completionHandler([.badge, .alert, .sound])
}
}
更新 2:在 Swift 2.3
中重写class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func applicationDidFinishLaunching(application: UIApplication) {
UNUserNotificationCenter.currentNotificationCenter().delegate = self
UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptions([.Badge, .Sound, .Alert]) { (granted, error) in
if granted {
self.registerCategory()
self.scheduleNotification("test", interval: 3)
self.scheduleNotification("test2", interval: 5)
}
}
}
func registerCategory() -> Void{
let callNow = UNNotificationAction(identifier: "call", title: "Call now", options: [])
let clear = UNNotificationAction(identifier: "clear", title: "Clear", options: [])
let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])
let center = UNUserNotificationCenter.currentNotificationCenter()
center.setNotificationCategories([category])
}
func scheduleNotification(event : String, interval: NSTimeInterval) {
let content = UNMutableNotificationContent()
content.title = event
content.body = "body"
content.categoryIdentifier = "CALLINNOTIFICATION"
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
let identifier = "id_"+event
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
let center = UNUserNotificationCenter.currentNotificationCenter()
center.addNotificationRequest(request) { (error) in
}
}
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
completionHandler([.Badge, .Alert, .Sound])
}
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
print("didReceive")
completionHandler()
}
}
我找到了这个问题的答案。当 运行 app on Xcode 8 with Swift 2.3 和最小部署目标为 iOS 9.3.
时调用下面的委托方法func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)
在swift3.0中使用,
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void)
使用 belwo 委托方法 Swift 2.3:
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)
为Swift3.0
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("** willPresent")
completionHandler([.badge, .alert, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
print("** didReceive")
completionHandler()
}
文档说要在 applicationWillFinishLaunching(:) 或 applicationDidFinishLaunching(:) 中设置委托。所以在 AppDelegate 中包含以下代码:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
}
设置此委托后,将调用以下 willPresent 函数。
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
completionHandler([.alert, .sound])
}
检查以确保只有您的 AppDelegate 被设置为 UNUserNotificationCenter Delegate。
你在使用...
UNUserNotificationCenter.current().delegate = self
...不止一次?我试图通过更改每个视图控制器中的委托并让每个视图控制器都使用此函数来捕获所有视图控制器中具有不同结果的通知:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
// code
}
我的问题是我还没有实现它们的功能,所以我的 AppDelegate 中的原始 userNotificationCenter 函数 "didReceive" 没有被调用。这可能就是您的电话未被调用的原因。
我遇到了同样的问题。
正在替换
[UNCalendarNotificationTrigger triggerWithDateMatchingComponents:dateComponents repeats:NO];
有
[UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];
对我有帮助。当然这还有其他作用,但至少现在可以用了