How can I register user's ios device for receiving push messages from place other than AppDelegate?

为君一笑 提交于 2019-12-12 05:38:23

问题


Currently in my appDelegate in didFinishLaunchingWithOptions I'm calling the following methods:

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

application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()

I also have the following methods implemented in AppDelegate:

didRegisterForRemoteNotificationsWithDeviceToken

didFailToRegisterForRemoteNotificationsWithError

didReceiveRemoteNotification

When user starts my app for the first time, he sees the popup that ask him for permission about receiving push messages.

I want to postpone showing this popup until user manually chooses specific option in Settings menu.

In Settings menu I have a UISwitch and I'm checking the state of it every time user changes it:

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

Is there a way of moving the push handling from app delegate to the settings menu, so that user sees the popup not immediately after starting the app, but when he selects the UISwitch? Also - will that work for future and all push functionality works well if I move it to Settings class?


回答1:


You can access the UIApplication instance provided to you in didFinishLaunchingWithOptions by accessing UIApplication.shared class property from anywhere in your application, where you have access to UIKit. I usually create a wrapper class that manages notifications, which would allow you to inject UIApplication dependency when you're writing unit tests later.

The register calls should happen when you're activating the switch:

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()
    }
}

A simplified wrapper class I use (singleton used for simplicity):

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()
    }
}

This requires that you call setup in your didFinishLaunchingMethod:

NotificationManager.shared.setup(application: application)

But then wherever you need to register for the notifications:

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

This allows you to easily test NotificationManager class by injecting an UIApplication mock object later on and the class also nicely encapsulates all notification related logic. With some modifications it can easily keep track if you already registered, keep track of the push token you received and even handle iOS 8/9 backward compatibility without duplicating boilerplate code.



来源:https://stackoverflow.com/questions/40866890/how-can-i-register-users-ios-device-for-receiving-push-messages-from-place-othe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!