UIApplication.registerForRemoteNotifications () solo debe invocarse desde el hilo principal

Xcode 9 (iOS 11) mostrándome un error / advertencia al registrarme para la notificación Push (remota).

Aquí está el mensaje de error

enter image description here

Y aquí está el código, lo he intentado:

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

Línea de error / advertencia:

UIApplication.shared.registerForRemoteNotifications ()

¿Cómo resolver esto?

En swift4

Puedes resolver este problema con

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

Espero que esto ayude …

Para Objective C, el siguiente código funciona

  dispatch_async(dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication] registerForRemoteNotifications]; }); 

TL; DR:
Todas las manipulaciones de la interfaz de usuario se deben realizar en el hilo principal para evitar problemas. Si no lo hiciera, el Comprobador principal de subprocesos (función de depuración introducida recientemente en XCode 9) producirá problemas en Runtime. Así que ajuste su código en el bloque de subprocesos principal como se muestra a continuación para evitar problemas técnicos y advertencias de tiempo de ejecución.

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

En versiones de Xcode antes de ver. 9, las advertencias relacionadas con el hilo principal se imprimirían textualmente en el área de la consola. De todos modos, puede desactivar opcionalmente ( no es un enfoque recomendado ) el Comprobador de subprocesos principal en la configuración de Diagnóstico en Editar Esquema .

Explicación:

Apple introdujo una nueva opción de depuración en XCode 9 para verificar problemas en Runtime para UIKit y otras API que manipulan elementos de la interfaz de usuario. Si hay algún cambio en los elementos de la interfaz de usuario de la API de UIKit en tiempo de ejecución, sin un bloque de hilos principal, es muy probable que cause problemas técnicos y lockings en la interfaz de usuario. El Comprobador de subprocesos principal está habilitado de forma predeterminada para detectar esos problemas en el tiempo de ejecución. Puede desactivar el Comprobador principal de subprocesos en la ventana Editar esquema al igual que a continuación, aunque en realidad no se recomienda hacerlo:

Deshabilitar el Comprobador de hilo principal

Si tiene SDK o marcos anteriores, al actualizar a Xcode 9, puede enfrentar esta advertencia, ya que algunas de las llamadas al método UIKit no se habrían envuelto en el hilo principal. Actualizarlos a la última versión solucionaría el problema (si el desarrollador es consciente de ello y lo solucionó).

Cita de las notas de la versión XCode 9 beta:

  • Nuevo en Xcode 9 – Comprobador de hilo principal.
    • Habilitar la detección del uso indebido de la API de la interfaz de usuario desde la cadena
    • Detecta las llamadas al método AppKit, UIKit y WebKit que no están hechas en el hilo principal.
    • Se habilita automáticamente durante la depuración y se puede desactivar en la pestaña Diagnóstico del editor de esquemas.
    • Main Thread Checker funciona con los idiomas Swift y C.

El mensaje de error es bastante claro: despacha registerForRemoteNotifications al hilo principal.

Usaría el parámetro granted y manejaría el error consecuencia

 center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } else { print(error!) // handle the error } } 

Esta es también la forma correcta de hacerlo en 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() } } }) 

Espero que esto ayude

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

Esto es lo que funcionó para mí. Cortesía de @ Mason11987 en el comentario aceptado arriba.

 DispatchQueue.main.async() { code }