Xcode 9 (iOS 11) wyświetla mi błąd / ostrzeżenie podczas rejestracji w celu otrzymania (zdalnego) powiadomienia.
Oto komunikat o błędzie
A oto kod, próbowałem:
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
if error == nil{
UIApplication.shared.registerForRemoteNotifications()
}
}
Linia błędu / ostrzeżenia:
UIApplication.shared.registerForRemoteNotifications ()
Jak rozwiązać ten problem?
UIApplication.shared.registerForRemoteNotifications()
w głównym wątku. :) Google jak to nazwać w głównym wątku ...UIApplication.shared.registerForRemoteNotifications()
nie jest związane z interfejsem użytkownika (nie monitujesz użytkowników, gdy otrzymasz token do cichych powiadomień). Więc wiersz, który pokazuje błąd, jest mylący. Jednak rejestracja w celu uzyskania odznak, alertów, dźwięków jest związana z interfejsem użytkownika i znacznie lepiej jest zrobić to z głównego wątku ... więc ogólnie cały blokcenter.requestAuthorization(options:...
musi być zrobiony z głównego wątku ... ma to sensOdpowiedzi:
W swift4
Możesz rozwiązać ten problem za pomocą
DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() }
Mam nadzieję, że to pomoże ...
źródło
DispatchQueue.main.async(execute: UIApplication.shared.registerForRemoteNotifications())
Cannot invoke 'async' with an argument list of type '(execute: Void)'
błąd na Twoim przykładzie.DispatchQueue.main.async(execute: UIApplication.shared.registerForRemoteNotifications)
.execute
oczekuje funkcji / zamknięcia typu,() -> Void
więcregisterForRemoteNotifications
działadispatch_async(dispatch_get_main_queue(), ^{ //Do stuff });
Poniższy kod działa w przypadku celu C
dispatch_async(dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication] registerForRemoteNotifications]; });
źródło
TL; DR:
Wszystkie manipulacje interfejsem użytkownika należy wykonywać w głównym wątku, aby uniknąć problemów. Jeśli tego nie zrobi, Main Thread Checker (nowo wprowadzona funkcja debugowania w XCode 9) spowoduje problemy w czasie wykonywania. Więc zawiń swój kod w bloku głównego wątku, jak poniżej, aby uniknąć usterek i ostrzeżeń w czasie wykonywania.
DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() }
W wydaniach Xcode przed wer. 9, ostrzeżenia związane z głównym wątkiem byłyby drukowane w obszarze konsoli tekstowo. W każdym razie możesz opcjonalnie wyłączyć ( nie jest to zalecane podejście ) Kontroler głównego wątku w ustawieniach diagnostycznych w Edytuj schemat .
Wyjaśnienie:
Firma Apple wprowadziła nową opcję debugowania w XCode 9 do sprawdzania problemów w czasie wykonywania dla UIKit i innych interfejsów API, które manipulują elementami interfejsu użytkownika. Jeśli wystąpią jakiekolwiek zmiany w elementach interfejsu użytkownika z interfejsu API UIKit w czasie wykonywania, bez bloku wątku głównego, jest wysoce prawdopodobne, że spowoduje to usterki interfejsu użytkownika i awarie. Narzędzie do sprawdzania wątków głównych jest domyślnie włączone, aby wychwytywać te problemy w czasie wykonywania. Możesz wyłączyć Kontroler wątków głównych w oknie Edytuj schemat, tak jak poniżej, chociaż nie jest to zalecane:
Jeśli masz jakieś starsze SDK lub frameworki, podczas aktualizacji do Xcode 9 możesz napotkać to ostrzeżenie, ponieważ niektóre wywołania metod UIKit nie zostałyby opakowane w główny wątek. Zaktualizowanie ich do najnowszej wersji rozwiązałoby problem (jeśli programista jest tego świadomy i naprawił go).
Cytat z informacji o wersji beta XCode 9:
źródło
Komunikat o błędzie jest dość jasny: wyślij
registerForRemoteNotifications
do głównego wątku.Chciałbym użyć
granted
parametru i obsługiwaćerror
odpowiedniocenter.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } else { print(error!) // handle the error } }
źródło
Jest to również poprawny sposób postępowania w 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() } } })
źródło
Mam nadzieję, że to pomoże
DispatchQueue.main.async(execute: { UIApplication.shared.registerForRemoteNotifications() })
źródło
To właśnie zadziałało dla mnie. Dzięki uprzejmości @ Mason11987 w zaakceptowanym komentarzu powyżej.
DispatchQueue.main.async() { code }
źródło