web-dev-qa-db-ja.com

UIApplication.registerForRemoteNotifications()はメインスレッドからのみ呼び出す必要があります

Xcode 9(iOS 11)は、プッシュ(リモート)通知の登録中にエラー/警告を表示します。

ここにエラーメッセージがあります

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

これを解決するには?

67
Krunal

In Swift4

この問題は次の方法で解決できます

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

これが役立つことを願っています...

121
Wasim K. Memon

Objective Cでは、以下のコードが機能します

    dispatch_async(dispatch_get_main_queue(), ^{
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    });
36
R. Mohan

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を無効にできます、実際にはそうすることはお勧めしませんが:

Disable Main Thread Checker

古いSDKまたはフレームワークがある場合、Xcode 9に更新すると、UIKitメソッド呼び出しの一部がメインスレッドにラップされないため、この警告が表示される場合があります。それらを最新バージョンに更新すると、問題が修正されます(開発者がそれを認識して修正した場合)。

XCode 9ベータリリースノートからの引用:

  • Xcode 9の新機能–メインスレッドチェッカー。
    • バックグラウンドスレッドからのUI API誤用の検出を有効にします
    • メインスレッドで行われないAppKit、UIKit、およびWebKitメソッドの呼び出しを検出します。
    • デバッグ中に自動的に有効になり、スキームエディターの[診断]タブで無効にできます。
    • メインスレッドチェッカーは、SwiftおよびC言語で動作します。
30
Badhan Ganesh

エラーメッセージは非常に明確です: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
        }
}
6
vadian

これはSwift 4.で行う正しい方法でもあります

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

これは私のために働いたものです。上記の承認済みコメントの@ Mason11987の好意による。

DispatchQueue.main.async() { code }
1
Gibraltar

これが役立つことを願って

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