未调用 iOS 10 UNUserNotificationCenterDelegate.推送通知不起作用
为了在 iOS10 中获得推送通知而费心思.当前设置:
Tearing my hair out tying to get push notifications to work in iOS10. Current setup:
在func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) ->布尔
:
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)
我已检查令牌已正确上传到后端,并且确实匹配.
I have checked the token is uploaded to the backend correctly and it does indeed match.
我也实现了:
@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")
}
我已经为所有目标设置了权限并启用推送:
I have set the entitlements for all targets and enabled push:
现在,当我尝试从后端发送消息时,设备什么也没收到.没有召集代表.不知道我在这里做错了什么.推送适用于 iOS9 和安卓设备.有什么指示我可能做错了什么吗?
Now when I try to send a message from the backend the device just receives nothing. Delegates are not being called. Have no idea what I'm doing wrong here. Push is working for iOS9 and android devices. Any pointers to what I might be doing wrong?
此答案适用于 iOS 10+,使用 UserNotifications
框架.
This answer pertains to iOS 10+, using the UserNotifications
framework.
您需要一个符合 UNUserNotificationCenterDelegate
协议的类.您是否为此创建了一个新类,或者将其添加到您的 AppDelegate
类中都没有关系.不过,我建议创建一个专门的类.就本回答而言,假设您为其创建了一个 UserNotificationController
类.
You need a class to conform to the UNUserNotificationCenterDelegate
protocol. It doesn't matter if you create a new class just for this, or add it on to your AppDelegate
class. I'd recommend creating a dedicated class though. For the purposes of this answer, let's assume you create a UserNotificationController
class for it.
该类可以有以下方法:
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
类的实例.您可能想要使用共享实例.
Then in your AppDelegate.application(_:didFinishLaunchingWithOptions:)
method, you need to set the delegate
on the UNUserNotificationCenter.current()
object to an instance of your UserNotificationController
class. You'll probably want to use a shared instance.
使用UNUserNotificationCenter.requestAuthorization(options:completionHandler:)
方法请求用户授权以启用通知,并在completionHandler
中,勾选granted代码> 值.如果
true
,则通过调用 UIApplication.shared.registerForRemoteNotifications()
注册远程通知.
Request authorization from the user to enable notifications using the UNUserNotificationCenter.requestAuthorization(options:completionHandler:)
method, and in the completionHandler
, check the granted
value. If true
, register for remote notifications by calling UIApplication.shared.registerForRemoteNotifications()
.
现在,当应用收到推送通知时,可能会发生几种不同的情况.我会在这里尝试列出最常见的情况.
Now, when the app receives a push notification, there are several different situations that can happen. I'll try and list the most common cases here.
本地通知:
如果应用在前台,应用会调用UserNotificationController .userNotificationCenter(_:willPresent:withCompletionHandler:)
.
If the app is in the foreground, the app will call UserNotificationController .userNotificationCenter(_:willPresent:withCompletionHandler:)
.
如果应用程序在后台(运行与否),则在用户点击通知之前不会调用任何内容,此时应用程序将打开并调用 UserNotificationController .userNotificationCenter(_:didReceive:withCompletionHandler:)
.
If the app is in the background (running or not), nothing is called until the user taps the notification, at that point, the app will open and call UserNotificationController .userNotificationCenter(_:didReceive:withCompletionHandler:)
.
远程通知:
有效载荷的内容会影响发生的事情.有效载荷有三种情况,a) 只是普通的 alert
、badge
和 sound
选项 b) 包括 content-available
选项(设置为 1
或 true
) c) 包括 mutable-content
选项(设置为 1
或 true
).另外,在技术上 d) 您同时拥有 content-available
和 mutable-content
,但这只会触发这两种情况.
The content of the payload will affect what happens. There are three cases for the payload, a) just the normal alert
, badge
, and sound
options b) including the content-available
option (set to 1
or true
) c) including the mutable-content
option (set to 1
or true
). Plus there's technically d) where you have both content-available
and mutable-content
, but that just triggers both cases.
对于 a) 只是 alert
、sound
、badge
信息:
For a) just alert
, sound
, badge
info:
这与本地通知的工作方式相同.
This works the same as a local notification.
对于 b) content-available
== true:
For b) content-available
== true:
如果应用在前台,UserNotificationController .userNotificationCenter(_:willPresent:withCompletionHandler:)
被调用.
If the app is in the foreground, UserNotificationController .userNotificationCenter(_:willPresent:withCompletionHandler:)
is called.
如果应用程序在后台,(运行与否),AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
被调用,而不是你的 UserNotificationController 类.
If the app is in the background, (running or not), AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
is called, not one of the methods in your UserNotificationController
class.
对于 c) mutable-content
== true:
For c) mutable-content
== true:
如果您已将 UNNotificationServiceExtension
添加到您的应用程序,它将处理通知并可以修改内容.无论您的主应用程序的状态如何,都会发生这种情况.如果(可选修改)通知被用户点击,则它会像上面的本地通知一样处理.
If you've added a UNNotificationServiceExtension
to your application, it will handle the notification and can modify the content. This happens regardless of the state of your main application. If the (optionally modified) notification is tapped by the user it is then handled like a local notification above.
如果没有 UNNotificationServiceExtension
,通知将被视为上面的普通远程通知.
Without a UNNotificationServiceExtension
, the notification is treated like a normal remote notification above.
附加说明:
当使用mutable-content
时,你必须在payload中包含alert
信息,否则系统会将其视为不可变的,不会调用你的UNNotificationServiceExtension代码>.您修改后的通知仍必须包含
alert
信息,否则将使用原始通知负载.遗憾的是,没有办法阻止通知向用户显示.
When using mutable-content
, you must include alert
info in the payload, or the system will treat it as immutable and not call into your UNNotificationServiceExtension
. Your modified notification must still include alert
info, or the original notification payload will be used. Sadly there's no way to prevent the notification from appearing to the user.
使用content-available
时,如果用户在上次使用时强制退出应用,系统将不会重新启动应用或调用AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
.尽管它仍会显示任何警报、播放声音并更新有效载荷中指示的徽章.
When using content-available
, if the user force-quit the app the last time they used it, the system will not relaunch the app or call AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
. Though it will still display any alert, play the sound, and update the badge as indicated in the payload.