必须仅从主线程调用UIApplication.registerForRemoteNotifications()

时间:2017-06-06 13:28:58

标签: ios swift push-notification swift4 unusernotificationcenter

Xcode 9(iOS 11)在注册Push(远程)通知时显示错误/警告。

这是错误消息

enter image description here

以下是代码,我已尝试过:

let center  = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
        if error == nil{
              UIApplication.shared.registerForRemoteNotifications()
        }
 }

错误/警告线:

  

UIApplication.shared.registerForRemoteNotifications()

如何解决这个问题?

8 个答案:

答案 0 :(得分:121)

swift4

您可以使用

解决此问题
DispatchQueue.main.async(execute: {
  UIApplication.shared.registerForRemoteNotifications()
}) 

希望这会有所帮助......

答案 1 :(得分:36)

对于Objective C,以下代码可以使用

    dispatch_async(dispatch_get_main_queue(), ^{
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    });

答案 2 :(得分:30)

TL; DR:
所有UI操作都应在主线程中完成,以避免出现问题。如果没有这样做,主线程检查器(XCode 9中新引入的调试功能)将在运行时产生问题。因此,请将代码包装在主线程块中,如下所示,以避免毛刺和运行时警告。

DispatchQueue.main.async {
    UIApplication.shared.registerForRemoteNotifications()
}

在版本之前的Xcode版本中。 9,与主线程相关的警告将以文本方式打印在控制台区域中。无论如何,您可以选择在编辑方案诊断设置中禁用(不推荐的方法)主线程检查器。


说明:

Apple在XCode 9中引入了一个新的调试选项,用于检查运行时UIKit和其他操纵UI元素的API的问题。如果在运行时UIKit API对UI元素进行了任何更改,没有主线程块,则极有可能导致UI故障和崩溃。默认情况下启用主线程检查器以在运行时捕获这些问题。您可以在编辑方案窗口中禁用主线程检查器,如下所示,但建议不要这样做:

Disable Main Thread Checker

如果您有任何较旧的SDK或Frameworks,在更新到Xcode 9时,您可能会遇到此警告,因为某些UIKit方法调用不会包含在主线程中。将它们更新到最新版本可以解决问题(如果开发人员知道并修复它)。

引用XCode 9测试版发布说明:

  
      
  • Xcode 9中的新功能 - 主线程检查器。      
        
    • 启用UI API检测   滥用后台主题
    •   
    • 检测未在主线程上进行的AppKit,UIKit和WebKit方法调用。
    •   
    • 在调试期间自动启用,可以在方案编辑器的“诊断”选项卡中禁用。
    •   
    • 主线程检查器适用于Swift和C语言。
    •   
  •   

答案 3 :(得分:6)

错误信息非常明确:将registerForRemoteNotifications发送到主线程。

我会使用granted参数并相应地处理error

center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
        if granted {
              DispatchQueue.main.async {
                  UIApplication.shared.registerForRemoteNotifications()
              }
        } else {
           print(error!)
           // handle the error
        }
}

答案 4 :(得分:3)

这也是正确的方法 Swift 4.0

UNUserNotificationCenter.current().delegate = self
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge], completionHandler: {(granted,error) in
            if granted{
                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            }
        })

答案 5 :(得分:2)

在 swift 4 或 5 中

DispatchQueue.main.async {
  UIApplication.shared.registerForRemoteNotifications()
}

在 Objectiv-C 上

dispatch_async(dispatch_get_main_queue(), ^{
        [[UIApplication sharedApplication] registerForRemoteNotifications];
});

答案 6 :(得分:1)

希望这会有所帮助

DispatchQueue.main.async(execute: {
  UIApplication.shared.registerForRemoteNotifications()
})

答案 7 :(得分:1)

这对我有用。感谢@ Mason11987在上面接受的评论中。

DispatchQueue.main.async() { code }