Comprobador de subprocesos principal: API de interfaz de usuario llamada en un subproceso en segundo plano: - [UIApplication applicationState]

107

Estoy usando mapas de Google en Xcode 9 beta, iOS 11.

Recibo un error en el registro de la siguiente manera:

Comprobador de subprocesos principal: API de interfaz de usuario llamada en un subproceso en segundo plano: - [UIApplication applicationState] PID: 4442, TID: 837820, Nombre del subproceso: com.google.Maps.LabelingBehavior, Nombre de la cola: com.apple.root.default-qos.overcommit , QoS: 21

¿Por qué ocurriría esto? Estoy casi seguro de que no estoy alterando ningún elemento de la interfaz del hilo principal en mi código.

 override func viewDidLoad() {

    let locationManager = CLLocationManager()


    locationManager.requestAlwaysAuthorization()


    locationManager.requestWhenInUseAuthorization()

        if CLLocationManager.locationServicesEnabled() {

            locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
            locationManager.startUpdatingLocation()
        }

      viewMap.delegate = self

     let camera = GMSCameraPosition.camera(withLatitude: 53.7931183329367, longitude: -1.53649874031544, zoom: 17.0)


        viewMap.animate(to: camera)


    }

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let locValue:CLLocationCoordinate2D = manager.location!.coordinate
        print("locations = \(locValue.latitude) \(locValue.longitude)")
    }

    func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {


    }

    func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {

        if(moving > 1){
            moving = 1
        UIView.animate(withDuration: 0.5, delay: 0, animations: {

            self.topBarConstraint.constant = self.topBarConstraint.constant + (self.topBar.bounds.height / 2)

            self.bottomHalfConstraint.constant = self.bottomHalfConstraint.constant + (self.topBar.bounds.height / 2)

            self.view.layoutIfNeeded()
        }, completion: nil)
    }
         moving = 1
    }


    // Camera change Position this methods will call every time
    func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
        moving = moving + 1
        if(moving == 2){


            UIView.animate(withDuration: 0.5, delay: 0, animations: {


                self.topBarConstraint.constant = self.topBarConstraint.constant - (self.topBar.bounds.height / 2)

                self.bottomHalfConstraint.constant = self.bottomHalfConstraint.constant - (self.topBar.bounds.height / 2)


                self.view.layoutIfNeeded()
            }, completion: nil)
        }
        DispatchQueue.main.async {

            print("Moving: \(moving) Latitude: \(self.viewMap.camera.target.latitude)")
            print("Moving: \(moving)  Longitude: \(self.viewMap.camera.target.longitude)")
        }
    }
Negro mate
fuente
1
En mapView(_:didChange), está enviando las printdeclaraciones a la cola principal. ¿No estás ya en la cola principal? De lo contrario, también debe enviar la animatellamada a la cola principal. Sugeriría insertar algunos dispatchPrecondition(condition: .onQueue(.main))antes de esas actualizaciones de la interfaz de usuario, solo para asegurarse.
Rob
Dijiste "Estoy casi seguro de que no alteraré ningún elemento de la interfaz del hilo principal de mi código". Supongo que quisiste decir "... de cualquier hilo de fondo".
Rob
2
No es tu problema. Creo que está al final. Se detiene en "com.google.Maps.LabelingBehavior". Yo tengo el mismo problema.
Tarvo Mäesepp
2
Hola, sí, el problema parece estar en Google, con suerte lanzarán una versión actualizada pronto
MattBlack
1
@MattBlack Eche un vistazo a esta respuesta: stackoverflow.com/a/44392584/5912335
badhanganesh

Respuestas:

54

Primero, asegúrese de que sus invocaciones de mapas de Google y cambios de interfaz de usuario se llamen desde el hilo principal.

Puede habilitar Thread Sanitizer para encontrar líneas ofensivas.

Puede poner líneas ofensivas en el hilo principal con lo siguiente:

DispatchQueue.main.async {
    //Do UI Code here. 
    //Call Google maps methods.
}

Además, actualice su versión actual de Google Maps. Los mapas de Google tuvieron que hacer un par de actualizaciones para el verificador de hilos.

Para la pregunta: "¿Por qué estaría ocurriendo esto?" Creo que Apple agregó una afirmación para un caso límite para el que Google tuvo que actualizar su pod.

ScottyBlades
fuente
1
@thibautnoah, ¿estás diciendo eso porque no lo expresé como "(el problema) está ocurriendo porque estás usando xcode 9 beta en combinación con la API de Google?" ¿O porque se enfrenta a un error similar que no se resuelve con mi respuesta?
ScottyBlades
7
Xcode 9 destacó algunos problemas de subprocesos que xcode 8 aparentemente no detecta (si se debe a la configuración de xcode u otra cosa por determinar). Volver a xcode 8 es equivalente a ignorar sus problemas de subprocesos, todavía están ahí y no están resueltos, por lo que no es una solución, simplemente está enterrando la cabeza en la arena y pretendiendo que todo está bien. Si el problema proviene de un marco, envíe un problema para que se pueda solucionar.
thibaut noah
Xcode 9 detecta problemas de subprocesos que xcode 8 no proporciona para detectar, Y Xcode 9 en combinación con la API de Google probablemente cause este error. Este error está ubicado en el depurador para múltiples bloqueos Y los bloqueos ya no ocurren cuando vuelve a xcode 8.
ScottyBlades
El punto es que el verificador de hilos muestra el síntoma, no la causa. Estoy diciendo que Xcode 9 beta es tanto la causa como el comunicador de síntomas. "los bloqueos ya no ocurren cuando vuelves a xcode 8". Existe una diferencia entre las advertencias de XCode y los bloqueos reales con las lecturas del depurador. Este error puede aparecer como una advertencia O como un bloqueo. El bloqueo desaparece por completo al volver a xcode 8. Xcode 9 beta se llama beta por una buena razón.
ScottyBlades
2
Sí ... creo que es difícil para muchos desarrolladores de iOS ver que solo porque algo muestre el síntoma, no significa que esté garantizado que no será la causa también. Creo que también es difícil aceptar que Apple alguna vez haya cometido un error.
ScottyBlades
156

Es difícil encontrar el código de la interfaz de usuario que a veces no se ejecuta en el hilo principal. Puede usar el siguiente truco para localizarlo y solucionarlo.

  1. Elija Editar esquema -> Diagnóstico, marque Comprobador de hilo principal.

    Xcode 11.4.1

    Haga clic en la flecha pequeña junto al Comprobador de hilo principal para crear un punto de interrupción del Comprobador de hilo principal. ingrese la descripción de la imagen aquí

    Xcode anterior

    Marque la casilla Pausa en los problemas. ingrese la descripción de la imagen aquí

  2. Ejecute su aplicación iOS para reproducir este problema. (Xcode debería detenerse en el primer problema). ingrese la descripción de la imagen aquí

  3. Envuelva el código que modifica la interfaz de usuario en DispatchQueue.main.async {} ingrese la descripción de la imagen aquí

UnchartedWorks
fuente
4
Gracias, ahórrame unos 30 minutos.
Orange
10
Por alguna razón, cuando hago eso en Xcode 10.1, solo obtengo una pila de llamadas que está indefensa y que no puedo relacionar con una línea de código: 2018-12-29 19: 46: 56.500629 + 0100 BedtimePrototype [1553: 834478] [informes ] Comprobador de subprocesos principal: API de interfaz de usuario llamada en un subproceso en segundo plano: - [UIApplication applicationState] PID: 1553, TID: 834478, Nombre del subproceso: com.apple.CoreMotion.MotionThread, Nombre de la cola: com.apple.root.default-qos. overcommit, QoS: 0
Vilmir
1
También tengo una pila de llamadas que parece impotente. En el lado izquierdo se detuvo en "com.apple.CoreMotion.MotionThread(23)", luego reviso todos los demás hilos también. En Thread 1algo me llamó la atención: es SVProgressHUD (una biblioteca de vista de progreso que usé). Entonces, sé que es una llamada a SVProgressHUD.show()algún lugar del controlador de vista de destino. Luego, envuelva cada apariencia DispatchQueue.main.asynco simplemente comente, pruebe nuevamente y descubrí cuál es problemática.
John Pang
2
También me deshice de la advertencia comentando SVProgressHUD.show. Envolver esta llamada en un DispatchQueue.main.async no eliminó la advertencia. Utilizo el pod en v2.2.5 Este hilo puede ayudar a comprender mejor el problema: github.com/SVProgressHUD/SVProgressHUD/issues/950
Vilmir
1
La casilla de verificación "Pausar problemas" no está ahí para mí en xcode 11.4.1. Editar: encontré una pequeña flecha al lado del Comprobador de hilo principal. Hacer clic en eso agrega un punto de interrupción para usted.
ChrisO
47

Envuelva las líneas de código que modifican la interfaz de usuario DispatchQueue.main.async {}para asegurarse de que se ejecutan en el hilo principal. De lo contrario, es posible que los esté llamando desde un hilo en segundo plano, donde no se permiten modificaciones de la interfaz de usuario. Todas estas líneas de código deben ejecutarse desde el hilo principal.

Toma
fuente
4
sí, ya lo he usado pero la advertencia todavía está presente
MattBlack
@Pang, se usa para imprimir cosas, no para el código de la interfaz de usuario principal.
Toma
4
@MattBlack intenta envolver todas las cosas que modifican la interfaz de usuario en elDispatchQueue.main.async {}
Toma
@ user6603599-Funciona como un encanto
Sree
3

Consulte este enlace https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

Para mí, esto funcionó cuando llamé desde el bloque.

Krishna Chaitanya Bandaru
fuente
1
Si está utilizando Swift 4+, esta es la mejor solución que funciona perfectamente, gracias por ayudarme a ahorrar tiempo. He jugado con Scheme Editor, pero seguir los consejos de Apple es la mejor opción ahora y en el futuro.
AbuTaareq
-34

Elija esquema -> Diagnóstico, elimine el verificador de hilo principal, luego la advertencia desaparecerá. editor de esquemas

L.Peng
fuente
18
No creo que sea una buena idea. Aquí hay un problema que ha descubierto el verificador de hilos. La desactivación del verificador de subprocesos permitirá que este y los problemas futuros no se descubran, y provocará que se incurra en una deuda técnica futura para solucionar los problemas.
ablarg
1
En realidad, mi punto es que podemos hacer esto cuando usamos el renderizado de OpenGL es, porque no podemos renderizar el búfer de cuadros en el hilo principal. ¿Derecha?
L.Peng
1
Ah, entonces si no aparece la advertencia, ¿el problema no existe?
probado el
11
"¿Por qué sigue sonando mi detector de humo?" "Simplemente retire la batería, problema resuelto".
John Montgomery
Si la advertencia no aparece, ¿el problema no existe?
S. Gissel