Как контролировать, когда запрашивать у пользователя разрешения push-уведомлений в iOS

Я создал приложение для iPhone, используя Swift и Xcode 6, и структуру Parse для обработки сервисов.

Следуя инструкциям Parse по настройке push-уведомлений, инструкции сообщили, что я помещаю push-уведомления в файл делегирования приложения.

Это код, который я добавил в файл делегата приложения...

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var pushNotificationsController: PushNotificationController?


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

         // Register for Push Notifications
        self.pushNotificationsController = PushNotificationController()

        if application.respondsToSelector("registerUserNotificationSettings:") {
            println("registerUserNotificationSettings.RegisterForRemoteNotificatios")
            let userNotificationTypes: UIUserNotificationType = (.Alert | .Badge | .Sound)
            let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
            application.registerUserNotificationSettings(settings)
            application.registerForRemoteNotifications()
        }

        return true;
    }

    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        println("didRegisterForRemoteNotificationsWithDeviceToken")
        let installation = PFInstallation.currentInstallation()
        installation.setDeviceTokenFromData(deviceToken)
        installation.saveInBackground()
    }
}

Итак, что происходит, так это то, что как только приложение будет запущено в первый раз, пользователю будет предложено предоставить эти разрешения.

Что я хочу сделать, это только запрос для этих разрешений после определенного действия (т.е. во время прохода по функциям приложения), поэтому я могу предоставить немного больше контекста, почему мы хотели бы, чтобы они разрешить push-уведомления.

Это так же просто, как просто копировать приведенный ниже код в соответствующем ViewController, где я буду ожидать приглашения пользователя?

// In 'MainViewController.swift' file

func promptUserToRegisterPushNotifications() {
        // Register for Push Notifications
        self.pushNotificationsController = PushNotificationController()

        if application.respondsToSelector("registerUserNotificationSettings:") {
            println("registerUserNotificationSettings.RegisterForRemoteNotificatios")
            let userNotificationTypes: UIUserNotificationType = (.Alert | .Badge | .Sound)
            let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
            application.registerUserNotificationSettings(settings)
            application.registerForRemoteNotifications()
        }
}

func application(application: UIApplication,    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        println("didRegisterForRemoteNotificationsWithDeviceToken")
        let installation = PFInstallation.currentInstallation()
        installation.setDeviceTokenFromData(deviceToken)
        installation.saveInBackground()
}

спасибо!

Ответ 1

Ответ прост. Если вы хотите, чтобы пользователь был запрошен в другое время, например, нажатием кнопки, просто переместите код в отношении запроса в эту функцию (или вызовите promptUserToRegisterPushNotifications() откуда-то еще).

Надеюсь, что помогает:)

Ответ 2

Это для Swift 2. Я разместил promptUserToRegisterPushNotifications() в MainViewController.swift, но я оставил didRegisterForRemoteNotificationsWithDeviceToken в AppDelegate, потому что он не работал, когда я помещаю его в тот же MainViewController.swift.

// In 'MainViewController.swift' file
func promptUserToRegisterPushNotifications() {
    // Register for Push Notifications

    let application: UIApplication = UIApplication.sharedApplication()

    if application.respondsToSelector(#selector(UIApplication.registerUserNotificationSettings(_:))) {
        print("registerUserNotificationSettings.RegisterForRemoteNotificatios")

        let notificationSettings = UIUserNotificationSettings(
            forTypes: [.Badge, .Sound, .Alert], categories: nil)
        application.registerUserNotificationSettings(notificationSettings) // Register for Remote Push Notifications
        application.registerForRemoteNotifications()
    }
}


// In AppDelegate
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
    var tokenString = ""

    for i in 0..<deviceToken.length {
        tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
    }

    NSUserDefaults.standardUserDefaults().setObject(tokenString, forKey: "deviceToken")

    print("Device Token:", tokenString)

}

Ответ 3

Это метод, который я написал в коде и отлично работает после его запуска (didFinishLaunch)

class func registerNotification() {
    if #available(iOS 10.0, *) {
        // push notifications
        UNUserNotificationCenter.current().requestAuthorization(options: [.sound, .alert, .badge]) {
            (granted, error) in
            if (granted) {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }

        let center  = UNUserNotificationCenter.current()
        center.delegate = AppManager.appDel()
        center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
            if error == nil {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    } else {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()
    }
}