Controllo thread principale: API UI richiamata su un thread in background: - [UIApplication applicationState]


107

Sto usando Google Maps in Xcode 9 beta, iOS 11.

Viene visualizzato un errore nel registro come segue:

Controllo thread principale: API UI richiamata su un thread in background: - [UIApplication applicationState] PID: 4442, TID: 837820, nome thread: com.google.Maps.LabelingBehavior, nome coda: com.apple.root.default-qos.overcommit , QoS: 21

Perché questo dovrebbe accadere dato che sono quasi certo di non alterare alcun elemento dell'interfaccia dal thread principale nel mio codice.

 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)")
        }
    }

1
In mapView(_:didChange)stai inviando le printdichiarazioni alla coda principale. Non sei già nella coda principale? In caso contrario, devi anche inviare la animatechiamata alla coda principale. Suggerirei di inserirne alcuni dispatchPrecondition(condition: .onQueue(.main))prima di quegli aggiornamenti dell'interfaccia utente, solo per esserne sicuri.
Rob il

Hai detto "Sono quasi certo di non alterare alcun elemento dell'interfaccia dal thread principale nel mio codice." Presumo che intendessi "... da qualsiasi thread in background".
Rob il

2
Non è un tuo problema. Penso che sia alla loro fine. Si ferma in "com.google.Maps.LabelingBehavior". Ho lo stesso poblem.
Tarvo Mäesepp

2
Ciao, sì, il problema sembra riguardare Google, si spera che rilasceranno presto una versione aggiornata
MattBlack

1
@MattBlack Date un'occhiata a questa risposta: stackoverflow.com/a/44392584/5912335
badhanganesh

Risposte:


54

Innanzitutto, assicurati che le tue invocazioni di Google Maps e le modifiche dell'interfaccia utente siano chiamate dal thread principale.

Puoi abilitare Thread Sanitizer per trovare le linee offensive.

Puoi inserire linee offensive nel thread principale con quanto segue:

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

Inoltre, aggiorna la tua attuale versione di google maps. Google Maps ha dovuto fare un paio di aggiornamenti per il controllo dei thread.

Per la domanda: "Perché dovrebbe succedere?" Penso che Apple abbia aggiunto un'affermazione per un caso limite per cui Google ha dovuto aggiornare il proprio pod.


1
@thibautnoah, lo stai dicendo perché non l'ho definito come "(il problema) si sta verificando perché stai usando xcode 9 beta in combinazione con l'API di Google?" O perché stai affrontando un bug simile che non è stato risolto dalla mia risposta?
ScottyBlades

7
Xcode 9 ha evidenziato alcuni problemi di threading che xcode 8 apparentemente non rileva (se è dovuto alle impostazioni di xcode o deve essere determinato qualcos'altro). Tornare a xcode 8 equivale a ignorare i problemi di threading, sono ancora presenti e non sono stati risolti, quindi non è una soluzione, stai solo seppellendo la testa nella sabbia e facendo finta che tutto sia ok. Se il problema proviene da un framework, invia un problema in modo che possa essere risolto.
thibaut noah

Xcode 9 rileva problemi di threading che xcode 8 non è proporzionale al rilevamento, E Xcode 9 in combinazione con l'API di Google probabilmente causa questo bug. Questo bug si trova nel debugger per più arresti anomali E gli arresti anomali non si verificano più quando torni a xcode 8.
ScottyBlades

Il punto è che il controllo dei thread mostra il sintomo non la causa. Sto dicendo che Xcode 9 beta è sia la causa che il comunicatore dei sintomi. "i crash non si verificano più quando torni a xcode 8". C'è una differenza tra gli avvisi XCode e gli arresti anomali effettivi con le letture del debugger. Questo errore può essere visualizzato come un avviso O come un arresto anomalo. L'arresto anomalo scompare completamente quando si torna a xcode 8. Xcode 9 beta è chiamato beta per una buona ragione.
ScottyBlades

2
Sì ... Penso che sia difficile per molti sviluppatori iOS vedere che solo perché qualcosa sta mostrando il sintomo, non significa che sia garantito che non sia anche la causa. Penso che sia anche difficile accettare che Apple possa aver mai commesso un errore.
ScottyBlades

156

È difficile trovare il codice dell'interfaccia utente che a volte non viene eseguito nel thread principale. Puoi usare il trucco qui sotto per individuarlo e risolverlo.

  1. Scegli Modifica schema -> Diagnostica, seleziona Controllo thread principale.

    Xcode 11.4.1

    Fare clic sulla piccola freccia accanto al controllo thread principale per creare un punto di interruzione controllo thread principale. inserisci qui la descrizione dell'immagine

    Precedente Xcode

    Spunta su Pausa sui problemi. inserisci qui la descrizione dell'immagine

  2. Esegui la tua applicazione iOS per riprodurre questo problema. (Xcode dovrebbe fermarsi sul primo numero.) inserisci qui la descrizione dell'immagine

  3. Racchiudi il codice che modifica l'interfaccia utente DispatchQueue.main.async {} inserisci qui la descrizione dell'immagine


4
Grazie, risparmiami forse 30 minuti.
Orange

10
Per qualche motivo, quando lo faccio in Xcode 10.1, ottengo solo un callstack che è impotente e che non posso relazionarmi a una riga di codice: 2018-12-29 19: 46: 56.500629 + 0100 BedtimePrototype [1553: 834478] [rapporti ] Controllo thread principale: API UI richiamata su un thread in background: - [UIApplication applicationState] PID: 1553, TID: 834478, Nome thread: com.apple.CoreMotion.MotionThread, Nome coda: com.apple.root.default-qos. overcommit, QoS: 0
Vilmir

1
Ho anche uno stack di chiamate che sembra impotente. Sul lato sinistro si è fermato a "com.apple.CoreMotion.MotionThread(23)", quindi controllo anche tutti gli altri thread. In Thread 1qualcosa catturato la mia attenzione: si tratta di SVProgressHUD (una libreria di vista i progressi che ho usato). Quindi, so che è una chiamata da SVProgressHUD.show()qualche parte nel controller della vista di destinazione. Quindi avvolgi ogni aspetto DispatchQueue.main.asynco commentalo, prova di nuovo e ho scoperto quale è problematico.
John Pang

2
Mi sono anche sbarazzato dell'avvertimento commentando SVProgressHUD.show. Il wrapping di questa chiamata in DispatchQueue.main.async non ha eliminato l'avviso. Uso il pod nella v2.2.5 Questo thread può aiutare a comprendere meglio il problema: github.com/SVProgressHUD/SVProgressHUD/issues/950
Vilmir

1
La casella di controllo "Pausa in caso di problemi" non è presente in xcode 11.4.1. Modifica: ho trovato una piccola freccia accanto al controllo thread principale. Fare clic su questo aggiunge un punto di interruzione per te.
ChrisO

47

Racchiudi le righe di codice che modificano l'interfaccia utente DispatchQueue.main.async {}per assicurarti che vengano eseguite sul thread principale. Altrimenti, potresti chiamarli da un thread in background, dove le modifiche dell'interfaccia utente non sono consentite. Tutte queste righe di codice devono essere eseguite dal thread principale.


4
sì, l'ho già usato ma l'avviso è ancora presente
MattBlack

@Pang, è usato per stampare cose, non per il codice dell'interfaccia utente principale.
Toma

4
@MattBlack tenta di avvolgere tutte le cose che modificano l'interfaccia utente suDispatchQueue.main.async {}
Toma

@ user6603599-Funziona come un incantesimo
Sree



-34

Scegli schema -> Diagnostica, rimuovi il controllo thread principale, quindi l'avviso scomparirà. editor di schemi


18
Non credo che questa sia una buona idea. C'è un problema qui che il controllo thread ha scoperto. La disattivazione del controllo thread consentirà a questo e a problemi futuri di non essere scoperti e causerà il futuro debito tecnico per risolvere i problemi.
ablarg

1
In realtà, il mio punto è che possiamo farlo quando usiamo il rendering OpenGL es, perché non possiamo rendere il frame buffer nel thread principale. giusto?
L.Peng

1
Ah, quindi se l'avvertenza non compare il problema non esiste?
turingtested il

11
"Perché il mio rilevatore di fumo continua a spegnersi?" "Basta rimuovere la batteria, problema risolto."
John Montgomery

Se l'avviso non compare il problema non esiste?
S. Gissel
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.