如何注册用户的 ios 设备以接收来自 AppDelegate 以外的地方的推送消息?

Posted

技术标签:

【中文标题】如何注册用户的 ios 设备以接收来自 AppDelegate 以外的地方的推送消息?【英文标题】:How can I register user's ios device for receiving push messages from place other than AppDelegate? 【发布时间】:2016-11-29 13:16:55 【问题描述】:

目前在我的appDelegatedidFinishLaunchingWithOptions 中,我正在调用以下方法:

let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)

application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()

我在AppDelegate中也实现了以下方法:

didRegisterForRemoteNotificationsWithDeviceToken

didFailToRegisterForRemoteNotificationsWithError

didReceiveRemoteNotification

当用户第一次启动我的应用程序时,他会看到一个弹出窗口,询问他是否允许接收推送消息。

我想推迟显示此弹出窗口,直到用户在“设置”菜单中手动选择特定选项。

在“设置”菜单中,我有一个 UISwitch,每次用户更改它时我都会检查它的状态:

func messagesStateChanged(_ sender: UISwitch)
    if(sender.isOn)
        defaults.set("true", forKey: "popupMessages")
        defaults.synchronize()
     else 
        defaults.set("false", forKey: "popupMessages")
        defaults.synchronize()
    

有没有办法将push 处理从应用程序委托移动到设置菜单,以便用户在启动应用程序后不会立即看到弹出窗口,而是在他选择UISwitch 时看到?另外 - 如果我将它移到 Settings 类,这是否适用于未来并且所有 push 功能都可以正常工作?

【问题讨论】:

为什么要让经过批准的标准化设计模式变得更糟? 【参考方案1】:

您可以通过在您可以访问UIKit 的应用程序中的任何位置访问UIApplication.shared 类属性来访问didFinishLaunchingWithOptions 中提供给您的UIApplication 实例。我通常会创建一个管理通知的包装类,它允许您在以后编写单元测试时注入UIApplication 依赖项。

注册调用应该在您激活开关时发生:

func messagesStateChanged(_ sender: UISwitch)
    if(sender.isOn)
        defaults.set("true", forKey: "popupMessages")
        defaults.synchronize()

        let application = UIApplication.shared
        let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
        let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)

        application.registerUserNotificationSettings(pushNotificationSettings)
        application.registerForRemoteNotifications()
     else 
        defaults.set("false", forKey: "popupMessages")
        defaults.synchronize()
    

我使用的简化包装类(为简单起见使用单例):

class NotificationManager 
    static var shared = NotificationManager()

    private var application : UIApplication?

    func setup(application: UIApplication) 
        self.application = application
    

    func register () 
        guard let application = application else 
            print("Attempt to register without calling setup")
            return
        

        let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
        let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)

        application.registerUserNotificationSettings(pushNotificationSettings)
        application.registerForRemoteNotifications()
    

这要求您在didFinishLaunchingMethod 中调用 setup:

NotificationManager.shared.setup(application: application)

但是,无论您需要在哪里注册通知:

func messagesStateChanged(_ sender: UISwitch)
    if(sender.isOn)
        ...
        NotificationManager.shared.register()
    
    ...

这使您可以稍后通过注入UIApplication 模拟对象轻松测试NotificationManager 类,并且该类还很好地封装了所有与通知相关的逻辑。通过一些修改,它可以轻松跟踪您是否已经注册,跟踪您收到的推送令牌,甚至处理 ios 8/9 向后兼容性,而无需复制样板代码。

【讨论】:

能否分享一下该包装类的示例代码? 你去。更多地将其用作一个想法,而不是直接使用此解决方案。 我在这里问了一个后续问题***.com/questions/41025023/…你能看一下吗?

以上是关于如何注册用户的 ios 设备以接收来自 AppDelegate 以外的地方的推送消息?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 aws sns 中注册 iOS 设备令牌以接收推送通知?

如何注册 android 设备以通过 App Engine 后端接收推送通知?

实现推送通知服务器:如何检查传递设备令牌的消息是不是来自真实设备?

我们如何注册一个多平台应用程序以在 iOS 14 中接收通知?

iOS 上的 MDM 和 MAM 功能

如何在 iOS 后台运行服务以接收本地通知?