85

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

这是错误消息

在此处输入图像描述

这是代码,我试过了:

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

如何解决这个问题?

4

8 回答 8

149

swift4

你可以解决这个问题

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

希望这会有所帮助...

于 2017-06-06T14:22:32.933 回答
51

对于Objective C,以下代码有效

    dispatch_async(dispatch_get_main_queue(), ^{
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    });
于 2017-09-22T11:23:45.223 回答
37

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

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

在版本之前的 Xcode 版本中。9,与主线程相关的警告将以文本形式打印在控制台区域。无论如何,您可以选择在Edit Scheme的Diagnostic settings 中禁用(不是推荐的方法)主线程检查器。

解释:

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

禁用主线程检查器

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

引用 Xcode 9 beta 发行说明:

  • Xcode 9 中的新功能 - 主线程检查器。
  • **启用 UI API 检测

从后台线程滥用**

  • 检测不是在主线程上进行的 AppKit、UIKit 和 WebKit 方法调用。
  • 在调试过程中自动启用,并且可以在方案编辑器的诊断选项卡中禁用。
  • 主线程检查器适用于 Swift 和 C 语言。
于 2017-06-06T14:20:15.657 回答
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
        }
}
于 2017-06-06T15:13:39.817 回答
5

在 swift 4 或 5

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

关于 Objective-C

dispatch_async(dispatch_get_main_queue(), ^{
        [[UIApplication sharedApplication] registerForRemoteNotifications];
});
于 2021-03-07T15:52:59.407 回答
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()
                }
            }
        })
于 2017-11-03T06:16:45.677 回答
1

希望这会有所帮助

DispatchQueue.main.async(execute: {
  UIApplication.shared.registerForRemoteNotifications()
})
于 2017-12-20T14:30:35.153 回答
1

这对我有用。在上面接受的评论中由@Mason11987 提供。

DispatchQueue.main.async() { code }
于 2018-06-21T00:57:49.903 回答