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()
これを解決するには?
In Swift4
この問題は次の方法で解決できます
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
これが役立つことを願っています...
Objective Cでは、以下のコードが機能します
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
TL; DR:
すべてのUI操作は、問題を回避するためにメインスレッドで行う必要があります。そうしないと、メインスレッドチェッカー(XCode 9で新しく導入されたデバッグ機能)が実行時に問題を引き起こします。したがって、グリッチとランタイム警告を回避するために、コードを以下のようにMain Threadブロックでラップします。
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
バージョン前のXcodeリリースでは。 9、メインスレッドに関連する警告がコンソール領域にテキストで出力されます。とにかく、オプションで(推奨されないアプローチではなく)DiagnosticEdit Schemeの設定。
説明:
Appleは、UICodeのランタイムおよびUI要素を操作する他のAPIの問題をチェックするために、XCode 9に新しいデバッグオプションを導入しました。実行時にUIKit APIからメインスレッドブロックを使用せずにUI要素に変更を加えると、UIの不具合やクラッシュが発生する可能性が高くなります。 メインスレッドチェッカーは、実行時にこれらの問題をキャッチするためにデフォルトで有効になっています。以下のようにEdit SchemeウィンドウでMain Thread Checkerを無効にできます、実際にはそうすることはお勧めしませんが:
古いSDKまたはフレームワークがある場合、Xcode 9に更新すると、UIKitメソッド呼び出しの一部がメインスレッドにラップされないため、この警告が表示される場合があります。それらを最新バージョンに更新すると、問題が修正されます(開発者がそれを認識して修正した場合)。
XCode 9ベータリリースノートからの引用:
- Xcode 9の新機能–メインスレッドチェッカー。
- バックグラウンドスレッドからのUI API誤用の検出を有効にします
- メインスレッドで行われないAppKit、UIKit、およびWebKitメソッドの呼び出しを検出します。
- デバッグ中に自動的に有効になり、スキームエディターの[診断]タブで無効にできます。
- メインスレッドチェッカーは、SwiftおよびC言語で動作します。
エラーメッセージは非常に明確です: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.で行う正しい方法でもあります
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge], completionHandler: {(granted,error) in
if granted{
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
})
これは私のために働いたものです。上記の承認済みコメントの@ Mason11987の好意による。
DispatchQueue.main.async() { code }
これが役立つことを願って
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})