web-dev-qa-db-fra.com

UIApplication.registerForRemoteNotifications () doit être appelé à partir du thread principal uniquement.

Xcode 9 (iOS 11) m'indiquant une erreur/un avertissement lors de l'enregistrement d'une notification Push (à distance).

Voici un message d'erreur

enter image description here

Et voici le code, j'ai essayé:

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

Ligne d'erreur/d'avertissement:

UIApplication.shared.registerForRemoteNotifications ()

Comment résoudre ce problème?

71
Krunal

Dans Swift4

Vous pouvez résoudre ce problème avec

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

J'espère que cela aidera ...

127
Wasim K. Memon

Pour Objective C, le code ci-dessous fonctionne

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

TL; DR:
Toutes les manipulations de l'interface utilisateur doivent être effectuées dans le fil principal pour éviter les problèmes. Vérificateur de thread principal (La fonction de débogage nouvellement introduite dans XCode 9) produira des problèmes au moment de l'exécution. Alors insérez votre code dans le bloc Main Thread comme ci-dessous pour éviter les problèmes et les avertissements d'exécution.

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

Dans les versions Xcode avant ver. 9, les avertissements liés au fil principal seraient imprimés textuellement dans la zone de la console. Quoi qu'il en soit, vous pouvez éventuellement désactiver ( l'approche non recommandée ) le vérificateur de thread principal dans le diagnostic paramètres dans Éditer le schéma .


Explication:

Apple a introduit une nouvelle option de débogage dans XCode 9 pour la vérification des problèmes au niveau de Runtime pour UIKit et d'autres API manipulant des éléments de l'interface utilisateur. Si des modifications sont apportées aux éléments d'interface utilisateur à partir de l'API UIKit au moment de l'exécution, sans bloc de thread principal, il y a de fortes chances que cela provoque des dysfonctionnements et des pannes de l'interface utilisateur. Le vérificateur de thread principal est activé par défaut pour résoudre ces problèmes au moment de l'exécution. Vous pouvez désactiver le vérificateur de threads principal dans la fenêtre Éditer le schéma comme ci-dessous , bien que ce ne soit pas vraiment recommandé de le faire:

Disable Main Thread Checker

Si vous possédez des SDK ou des frameworks plus anciens, lors de la mise à jour vers Xcode 9, vous pouvez être confronté à cet avertissement car certains des appels de méthode UIKit n'auraient pas été encapsulés dans Main Thread. Le fait de les mettre à jour avec la dernière version résoudrait le problème (si le développeur le savait et le corrigeait).

Extrait des notes de publication de la version bêta de XCode 9:

  • Nouveau dans Xcode 9 - Vérificateur de thread principal.
    • Activer la détection d'abus de l'API de l'interface utilisateur à partir du thread d'arrière-plan
    • Détecte les appels de méthode AppKit, UIKit et WebKit qui ne sont pas effectués sur le thread principal.
    • Activé automatiquement lors du débogage et peut être désactivé dans l'onglet Diagnostic de l'éditeur de schéma.
    • Le vérificateur de thread principal fonctionne avec les langages Swift et C.
34
Badhan Ganesh

Le message d'erreur est assez clair: dispatch registerForRemoteNotifications sur le thread principal.

Je voudrais utiliser le paramètre granted et gérer le error en conséquence

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

C'est aussi une bonne façon de faire 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

C'est ce qui a fonctionné pour moi. Avec l'aimable autorisation de @ Mason11987 dans le commentaire accepté ci-dessus.

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

J'espère que cela aidera

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