Swift 4 – UIApplication.registerForRemoteNotifications()只能从主线程调用

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

这是错误信息

在这里输入图像说明

这里是代码,我试过了:

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

如何解决这个问题?

swift4

你可以用这个来解决这个问题

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

希望这将有助于…

TL; DR:
所有UI操作应该在主线程中完成以避免问题。 如果没有这样做, 主线程检查器 (在XCode 9中新引入的debuggingfunction)将在运行时产生问题。 您可以select(不是推荐的方法)在编辑scheme诊断设置中禁用主线程检查器

Apple在XCode 9中引入了一个新的debugging选项,用于在运行时检查UIKit和其他操作UI元素的API的问题。 如果在运行系统中UIKit API的UI元素没有主线程块,那么很可能会导致UI故障和崩溃。 主线程检查器默认情况下启用,以在运行时捕获这些问题。 您可以在编辑计划窗口中禁用主线程检查程序 ,就像下面一样,尽pipe并不真的build议这样做:

禁用主线程检查器

从XCode 9testing版发布说明引用:

  • Xcode 9中的新增function – 主线程检查器。
    • 从后台线程启用对UI API滥用的检测
    • 检测未在主线程上进行的AppKit,UIKit和WebKit方法调用。
    • 在debugging期间自动启用,并且可以在scheme编辑器的“诊断”选项卡中禁用。
    • 主线程检查器使用Swift和C语言。

对于Objective C,下面的代码起作用

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

错误消息非常清晰:向主线程发送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 } } 

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