且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

未调用 iOS 10 UNUserNotificationCenterDelegate.推送通知不起作用

更新时间:2023-02-27 09:20:06

此答案适用于 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) 只是普通的 alertbadgesound 选项 b) 包括 content-available 选项(设置为 1true) c) 包括 mutable-content 选项(设置为 1true).另外,在技术上 d) 您同时拥有 content-availablemutable-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) 只是 alertsoundbadge 信息:

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.