如何注册用户的ios设备以从Ap​​pDelegate以外的地方接收推送消息?

时间:2016-11-29 13:16:55

标签: ios objective-c swift apple-push-notifications appdelegate

目前在我的appDelegate didFinishLaunchingWithOptions我正在调用以下方法:

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处理从app delegate移动到设置菜单,以便用户在启动应用程序后不会立即看到弹出窗口,但是当他选择UISwitch时?此外 - 如果我将其移至设置类,那么未来和所有push功能是否都能正常工作?

1 个答案:

答案 0 :(得分:4)

您可以在应用中访问UIApplication的{​​{1}}类属性,访问didFinishLaunchingWithOptions中提供给您的UIApplication.shared实例。我通常会创建一个管理通知的包装类,这样可以在以后编写单元测试时注入UIKit依赖项。

当你激活开关时,应该发生注册调用:

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

但随后您需要注册通知:

NotificationManager.shared.setup(application: application)

这允许您稍后通过注入func messagesStateChanged(_ sender: UISwitch){ if(sender.isOn){ ... NotificationManager.shared.register() } ... } 模拟对象来轻松地测试NotificationManager类,并且该类也很好地封装了所有与通知相关的逻辑。通过一些修改,如果您已经注册,它可以轻松跟踪,跟踪您收到的推送令牌,甚至可以处理iOS 8/9向后兼容性,而无需复制样板代码。