必须`registerUserNotificationSettings:`在应用程序启动周期中调用?

the*_*ory 5 iphone permissions uikit push-notification ios

国家文件registerUserNotificationSettings::

如果您的应用显示警报,播放声音或标记其图标,则必须在启动周期中调用此方法以请求以这些方式提醒用户的权限.

我很失望地看到这一点,因为在需要之前,应用程序要求允许发送推送通知似乎很粗鲁.例如,在我正在设计的应用程序中,用户必须在有任何理由发送推送通知之前使用我们的在线服务创建帐户.而且可能是用户从不注册,只是在本地使用应用程序,所以从来没有任何理由要求.但是如果我只能在应用程序启动时询问,则意味着用户必须创建一个帐户,退出应用程序,然后在我们提出要求之前再次启动它.看起来很奇怪.

这真的有必要吗?我尝试将调用registerUserNotificationSettings:放入应用程序的更相关部分,但随后应用程序从未提示发送推送通知的权限.这只是iOS推送通知的策略,还是有一些方法可以更灵活地询问何时请求发送推送通知的权限?

the*_*ory 4

初始调用-registerForNotifications不必在应用程序启动周期期间调用。但是,在第一次调用之后,必须始终在应用程序启动周期期间调用它。

这里有两个问题,一个是我的问题,另一个是我用于推送通知的第三方服务的问题。我的问题是我解雇了-registerForNotifications返回后调用的视图控制器;我没有意识到它是异步运行的。所以我添加-application:didRegisterUserNotificationSettings到我的应用程序委托中。一旦用户响应了 提出的提示,就会调用此方法-registerForNotifications,并且我让它发布通知。在调用之前-registerForNotifications,我为该通知设置了一个侦听器,并且仅在收到通知后才关闭视图控制器。有点希望有一个委托或一个块来指定,但没有。

我怀疑没有的原因是因为 iOS确实希望您调用-registerForNotificationsin application:didFinishLaunchingWithOptions:,因此异步回调很自然地只是应用程序委托中的另一个方法。[删除了有关必须重新启动应用程序才能实际获取推送通知的信息。添加:]另一个问题是我用于推送通知的第三方服务(仍处于 Alpha 版本)通常不发送推送通知。一旦这个问题得到解决,一旦我批准推送通知,他们就开始工作,无论提示是在应用程序启动期间还是稍后出现。[/已添加]

这是完整的模式:

  • 如果已设置用户默认值,则在应用程序委托的application:didFinishLaunchingWithOptions:方法调用中:-registerForNotifications

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        if NSUserDefaults.standardUserDefaults().boolForKey("registedNotificationSettings") {
            self.registerForNotifications()
        }
        return true
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 在应用程序委托的-application:didRegisterUserNotificationSettings:方法中,配置远程通知、存储用户默认值并发布通知:

    func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
        if notificationSettings.types != .None {
            application.registerForRemoteNotifications()
        }
        let defaults = NSUserDefaults.standardUserDefaults()
        if !defaults.boolForKey( "registedNotificationSettings") {
            defaults.setBool(true, forKey: "registedNotificationSettings")
            defaults.synchronize()
        }
        NSNotificationCenter.defaultCenter().postNotification(
            NSNotification(name: "RegistedNotificationSettings", object: notificationSettings)
        )
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 在我的视图控制器中,按下按钮时,监听该通知,然后请求发送推送通知的权限:

    @IBAction func okayButtonTapped(sender: AnyObject) {
        NSNotificationCenter.defaultCenter().addObserver(
            self,
            selector: #selector(didRegisterNotificationSettings(_:)),
            name: "RegistedNotificationSettings",
            object: nil
        )
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appDelegate.registerForNotifications()
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 当然,我们需要通知方法,该方法在授予权限时关闭视图控制器,并在未授予权限时需要执行其他操作:

    func didRegisterNotificationSettings(notification: NSNotification) {
        let status = notification.object as! UIUserNotificationSettings
        if status.types != .None {
            // Yay!
            self.done()
            return
        }
    
        // Tell them a little more about it.
        NSLog("User declined push notifications")
        self.done()
    }
    
    Run Code Online (Sandbox Code Playgroud)

通过此配置,一切都可以[删除有关-registerForNotifications通话时间的错误信息],并且不会在应用程序启动时提示用户。