[英]iOS 10 UNUserNotificationCenterDelegate not called. push notifications not working
撕裂我的头发,以便在iOS10中使用推送通知。 目前的设置:
在func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
:
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if error == nil {
print("DID REQUEST THE NOTIFICATION")
UIApplication.shared.registerForRemoteNotifications()
}
}
print("DID SET DELEGATE")
}
在func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
:
print("DID REGISTER FOR A REMOTE NOTIFICATION AND THE TOKEN IS \(deviceToken.base64EncodedString())"
let request = UpdatePushNotificationSubscription_Request(deviceToken: deviceToken)
updatePushNotificationSubscriptionWorker.updateSubscription(request)
我已经检查过令牌是否正确上传到后端,它确实匹配。
我也实施了:
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("GOT A NOTIFICATION")
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
//This is for the user tapping on the notification
print("GOT A NOTIFICATION")
}
我已为所有目标设置权限并启用了推送:
现在当我尝试从后端发送消息时,设备什么都没有收到。 代表们没有被召集。 不知道我在这里做错了什么。 Push适用于iOS9和Android设备。 我可能做错了什么指针?
这个答案适用于使用UserNotifications
框架的iOS 10+。
您需要一个类符合UNUserNotificationCenterDelegate
协议。 如果您为此创建一个新类,或将其添加到您的AppDelegate
类,则无关紧要。 我建议创建一个专门的课程。 出于本答案的目的,我们假设您为它创建一个UserNotificationController
类。
该类可以具有以下方法:
optional func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
optional func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
然后在AppDelegate.application(_:didFinishLaunchingWithOptions:)
方法中,您需要将UNUserNotificationCenter.current()
对象上的delegate
设置为UserNotificationController
类的实例。 您可能希望使用共享实例。
请求用户授权以使用UNUserNotificationCenter.requestAuthorization(options:completionHandler:)
方法启用通知,并在completionHandler
中检查granted
值。 如果为true
,则通过调用UIApplication.shared.registerForRemoteNotifications()
注册远程通知。
现在,当应用程序收到推送通知时,可能会发生几种不同的情况。 我会尝试列出最常见的案例。
本地通知:
如果应用程序位于前台,则应用程序将调用UserNotificationController .userNotificationCenter(_:willPresent:withCompletionHandler:)
。
如果应用程序在后台(运行与否),则在用户点击通知之前不会调用任何内容,此时应用程序将打开并调用UserNotificationController .userNotificationCenter(_:didReceive:withCompletionHandler:)
。
远程通知:
有效载荷的内容将影响发生的事情。 有效载荷有三种情况:a)正常alert
, badge
和sound
选项b)包括content-available
选项(设置为1
或true
)c)包括mutable-content
选项(设置为1
或true
) 。 另外,技术上d)你有content-available
和mutable-content
,但这只会触发两种情况。
对于a) alert
, sound
, badge
信息:
这与本地通知相同。
对于b) content-available
== true:
如果应用程序位于前台,则UserNotificationController .userNotificationCenter(_:willPresent:withCompletionHandler:)
。
如果应用程序在后台(运行与否),则调用AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
,而不是UserNotificationController
类中的UserNotificationController
方法。
对于c) mutable-content
== true:
如果您已将UNNotificationServiceExtension
添加到应用程序,它将处理通知并可以修改内容。 无论主应用程序的状态如何,都会发生这种情况。 如果用户点击(可选地修改的)通知,则其被处理为类似于上面的本地通知。
如果没有UNNotificationServiceExtension
,通知将被视为上面的正常远程通知。
补充笔记:
使用mutable-content
,必须在有效负载中包含alert
信息,否则系统会将其视为不可变,而不是调用UNNotificationServiceExtension
。 您修改的通知仍必须包含alert
信息,否则将使用原始通知有效负载。 遗憾的是,没有办法阻止通知出现在用户身上。
当使用content-available
,如果用户上次使用它时强制退出应用程序,系统将不会重新启动应用程序或调用AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
。 虽然它仍然会显示任何警报,播放声音,并按照有效负载中的指示更新徽章。
尝试让AppDelegate类实现UNUserNotificationCenterDelegate协议,而不是实现协议的单独类。
我有一个单独的代表类,它没有用。 这就是我的代码在我工作时的样子:
import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application
UIApplication.shared.registerForRemoteNotifications()
let center = UNUserNotificationCenter.current()
center.delegate = self //DID NOT WORK WHEN self WAS MyOtherDelegateClass()
center.requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
// Enable or disable features based on authorization.
if granted {
// update application settings
}
}
return true
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent: UNNotification,
withCompletionHandler: @escaping (UNNotificationPresentationOptions)->()) {
withCompletionHandler([.alert, .sound, .badge])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive: UNNotificationResponse,
withCompletionHandler: @escaping ()->()) {
withCompletionHandler()
}
// and so forth for your other AppDelegate stuff
我整整都挣扎了一整天。 有时我收到通知,有时候没有收到通知,但我永远无法将userNotificationCenter(_:willPresent:completionHandler:)
回调发送到userNotificationCenter(_:willPresent:completionHandler:)
。
原来有两个问题。 第一个我仍然有点困惑:我的目标部署版本设置为11.0但我的项目设置为10.0。 将项目更改为11.0是第一步。 我不完全理解这一点但是10.0和11.0之间的通知处理可能有些不同吗?
第二部分是通知中心代表。 我在文档中注意到Apple的注释 : -
重要
在应用程序完成启动之前,您必须将代理对象分配给UNUserNotificationCenter对象。 例如,在iOS应用程序中,您必须在应用程序委托的应用程序( :willFinishLaunchingWithOptions :)或应用程序( :didFinishLaunchingWithOptions :)方法中分配它。 调用这些方法后分配委托可能会导致您错过传入通知。
我一直在设置一个单独的“通知管理器”类,这也是回调也位于的地方(作为委托协议实现)。 我已将其实例化为我的app委托中的实例var,假设这将在早期创建并且不会导致问题。
我搞乱了实例化等一段时间,但只有当我在我的application(_:didFinishLaunchingWithOptions:)
设置委托application(_:didFinishLaunchingWithOptions:)
方法并在app委托中实现了委托回调时,我设法修复它。
所以我的代码基本上成了: -
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// You MUST do this HERE and nowhere else!
UNUserNotificationCenter.current().delegate = self
// other stuff
return true
}
extension AppDelegate: UNUserNotificationCenterDelegate {
// These delegate methods MUST live in App Delegate and nowhere else!
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
if let userInfo = notification.request.content.userInfo as? [String : AnyObject] {
}
completionHandler(.alert)
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if let userInfo = response.notification.request.content.userInfo as? [String : AnyObject] {
}
completionHandler()
}
}
也许不设置UNNotificationCategory
的intentIdentifiers
,如果代码如下:
UNNotificationCategory* expiredCategory = [UNNotificationCategory
categoryWithIdentifier:@"TIMER_EXPIRED"
actions:@[snoozeAction, stopAction]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
它不会调用UNUserNotificationCenter的委托方法,因此您必须设置这样的intentIdentifiers:
UNNotificationCategory* expiredCategory = [UNNotificationCategory
categoryWithIdentifier:@"TIMER_EXPIRED"
actions:@[snoozeAction, stopAction]
intentIdentifiers:@[@"a",@"b"]
options:UNNotificationCategoryOptionCustomDismissAction];
除了确保您使用AppDelegate
用于UNUserNotificationCenter
委托,并在启动时在application:didFinishLaunchingWithOptions
方法中设置委托,请确保您还记得导入UserNotifications
和UserNotificationsUI
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.