Haupt-Thread-Checker: UI-API, die für einen Hintergrund-Thread aufgerufen wird: - [UIApplication applicationState]


107

Ich verwende Google Maps in Xcode 9 Beta, iOS 11.

Ich erhalte folgende Fehlermeldung im Protokoll:

Haupt-Thread-Checker: UI-API, die für einen Hintergrund-Thread aufgerufen wird: - [UIApplication applicationState] PID: 4442, TID: 837820, Thread-Name: com.google.Maps.LabelingBehavior, Warteschlangenname: com.apple.root.default-qos.overcommit , QoS: 21

Warum sollte dies passieren, da ich fast sicher bin, dass ich keine Schnittstellenelemente aus dem Hauptthread in meinem Code ändere?

 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)senden Sie die printAnweisungen an die Hauptwarteschlange. Stehen Sie noch nicht in der Hauptwarteschlange? Wenn nicht, müssen Sie den animateAnruf auch an die Hauptwarteschlange weiterleiten. Ich würde vorschlagen, dispatchPrecondition(condition: .onQueue(.main))vor diesen UI-Updates einige einzufügen, nur um sicherzugehen.
Rob

Sie sagten: "Ich bin fast sicher, dass ich keine Schnittstellenelemente aus dem Hauptthread in meinem Code ändere." Ich nehme an, Sie meinten "... aus einem Hintergrund-Thread".
Rob

2
Nicht dein Problem. Ich denke, es ist am Ende. Es stoppt in "com.google.Maps.LabelingBehavior". Ich habe das gleiche Problem.
Tarvo Mäesepp

2
Hallo, ja, das Problem scheint bei Google zu liegen, hoffentlich werden sie bald eine aktualisierte Version veröffentlichen
MattBlack

1
@ MattBlack Schauen Sie sich diese Antwort an: stackoverflow.com/a/44392584/5912335
badhanganesh

Antworten:


53

Stellen Sie zunächst sicher, dass Ihre Aufrufe von Google Maps und UI-Änderungen vom Haupt-Thread aufgerufen werden.

Sie können den Thread Sanitizer aktivieren , um fehlerhafte Linien zu finden.

Sie können den Haupt-Thread mit den folgenden Zeilen beleidigen:

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

Aktualisieren Sie außerdem Ihre aktuelle Version von Google Maps. Google Maps musste einige Aktualisierungen für den Thread-Checker vornehmen.

Für die Frage: "Warum sollte das passieren?" Ich denke, Apple hat eine Behauptung für einen Randfall hinzugefügt , für den Google dann seinen Pod aktualisieren musste.


1
@thibautnoah, sagen Sie das, weil ich es nicht als "es (das Problem) tritt auf, weil Sie xcode 9 beta in Kombination mit Googles API verwenden?" Oder weil Sie vor einem ähnlichen Fehler stehen, der durch meine Antwort nicht behoben wird?
ScottyBlades

7
Xcode 9 hat einige Threading-Probleme hervorgehoben, die Xcode 8 anscheinend nicht erkennt (ob dies auf Xcode-Einstellungen zurückzuführen ist oder eine andere Sache zu bestimmen ist). Das Zurückschalten auf xcode 8 entspricht dem Ignorieren Ihrer Threading-Probleme. Sie sind immer noch vorhanden und nicht gelöst. Daher ist dies keine Lösung. Sie vergraben nur Ihren Kopf im Sand und tun so, als wäre alles in Ordnung. Wenn das Problem von einem Framework stammt, reichen Sie bitte ein Problem ein, damit es behoben werden kann.
Thibaut Noah

Xcode 9 erkennt Threading-Probleme, die Xcode 8 nicht erkennt, und Xcode 9 in Kombination mit der Google-API verursacht wahrscheinlich diesen Fehler. Dieser Fehler befindet sich im Debugger für mehrere Abstürze UND die Abstürze treten nicht mehr auf, wenn Sie zurück zu xcode 8 wechseln.
ScottyBlades

Ihr Punkt ist, dass der Thread-Prüfer das Symptom anzeigt, nicht die Ursache. Ich sage, Xcode 9 Beta ist sowohl die Ursache als auch der Symptom-Kommunikator. "Die Abstürze treten nicht mehr auf, wenn Sie wieder zu xcode 8 wechseln." Es gibt einen Unterschied zwischen XCode-Warnungen und tatsächlichen Abstürzen mit Debugger-Anzeigen. Dieser Fehler kann als Warnung oder Absturz angezeigt werden. Der Absturz verschwindet vollständig, wenn Sie wieder zu xcode 8 wechseln. Xcode 9 Beta wird aus gutem Grund als Beta bezeichnet.
ScottyBlades

2
Ja ... Ich denke, es ist für viele iOS-Entwickler schwierig zu erkennen, dass nur, weil etwas das Symptom zeigt, dies nicht bedeutet, dass es garantiert nicht auch die Ursache ist. Ich denke, es ist auch schwer zu akzeptieren, dass Apple jemals einen Fehler gemacht hat.
ScottyBlades

156

Es ist schwierig, den UI-Code zu finden, der manchmal nicht im Hauptthread ausgeführt wird. Sie können den folgenden Trick verwenden, um es zu finden und zu beheben.

  1. Wählen Sie Schema bearbeiten -> Diagnose und aktivieren Sie das Kontrollkästchen Haupt-Thread-Checker.

    Xcode 11.4.1

    Klicken Sie auf den kleinen Pfeil neben dem Haupt-Thread-Checker, um einen Haltepunkt für den Haupt-Thread-Checker zu erstellen. Geben Sie hier die Bildbeschreibung ein

    Vorheriger Xcode

    Aktivieren Sie Pause bei Problemen. Geben Sie hier die Bildbeschreibung ein

  2. Führen Sie Ihre iOS-Anwendung aus, um dieses Problem zu reproduzieren. (Xcode sollte bei der ersten Ausgabe pausieren.) Geben Sie hier die Bildbeschreibung ein

  3. Wickeln Sie den Code ein, der die Benutzeroberfläche ändert DispatchQueue.main.async {} Geben Sie hier die Bildbeschreibung ein


4
Danke, spare mir vielleicht 30 Minuten.
Orange

10
Wenn ich das in Xcode 10.1 mache, bekomme ich aus irgendeinem Grund nur einen Callstack, der hilflos ist und den ich nicht mit einer Codezeile in Verbindung bringen kann: 2018-12-29 19: 46: 56.500629 + 0100 BedtimePrototype [1553: 834478] [Berichte ] Haupt-Thread-Checker: UI-API, die für einen Hintergrund-Thread aufgerufen wurde: - [UIApplication applicationState] PID: 1553, TID: 834478, Thread-Name: com.apple.CoreMotion.MotionThread, Warteschlangenname: com.apple.root.default-qos. Overcommit, QoS: 0
Vilmir

1
Ich habe auch einen Call-Stack bekommen, der hilflos aussieht. Auf der linken Seite hörte es auf "com.apple.CoreMotion.MotionThread(23)", dann überprüfe ich auch alle anderen Threads. In Thread 1etwas fiel mir auf: Es ist SVProgressHUD (eine von mir verwendete Fortschrittsanzeige-Bibliothek). Ich weiß also, dass es sich um einen Aufruf an einen SVProgressHUD.show()beliebigen Ort im Target View Controller handelt. Dann entweder jeden Auftritt einwickeln DispatchQueue.main.asyncoder einfach auskommentieren, erneut testen und ich fand heraus, welcher problematisch ist.
John Pang

2
Ich habe die Warnung auch durch Auskommentieren von SVProgressHUD.show beseitigt. Durch das Umschließen dieses Aufrufs in eine DispatchQueue.main.async wurde die Warnung nicht entfernt. Ich benutze den Pod in v2.2.5 Dieser Thread kann helfen, das Problem besser zu verstehen: github.com/SVProgressHUD/SVProgressHUD/issues/950
Vilmir

1
Das Kontrollkästchen "Pause bei Problemen" ist in xcode 11.4.1 für mich nicht vorhanden. Bearbeiten: Ich habe einen kleinen Pfeil neben dem Haupt-Thread-Checker gefunden. Wenn Sie darauf klicken, wird ein Haltepunkt für Sie hinzugefügt.
ChrisO

47

Schließen Sie die Codezeilen ein, die die Benutzeroberfläche ändern DispatchQueue.main.async {}, um sicherzustellen, dass sie im Hauptthread ausgeführt werden. Andernfalls rufen Sie sie möglicherweise von einem Hintergrund-Thread aus auf, in dem Änderungen an der Benutzeroberfläche nicht zulässig sind. Alle diese Codezeilen müssen vom Hauptthread ausgeführt werden.


4
Ja, ich habe das bereits benutzt, aber die Warnung ist immer noch vorhanden
MattBlack

@Pang, es wird zum Drucken von Dingen verwendet, nicht für den Haupt-UI-Code.
Dimitrie-Toma Furdui

4
@ MattBlack versuchen, alle Dinge zu verpacken, die die Benutzeroberfläche auf demDispatchQueue.main.async {}
Dimitrie-Toma Furdui

@ user6603599-Funktioniert wie ein Zauber
Sree

3

Verweisen Sie auf diesen Link https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

Bei mir hat das geklappt, als ich aus dem Block angerufen habe.


1
Wenn Sie Swift 4+ verwenden, ist dies die beste Lösung, die perfekt funktioniert. Vielen Dank, dass Sie mir geholfen haben, meine Zeit zu sparen. Ich habe mit dem Schema-Editor gespielt, aber den Ratschlägen von Apple zu folgen, ist jetzt die beste Option und geht weiter.
AbuTaareq


-34

Wählen Sie Schema -> Diagnose, entfernen Sie den Haupt-Thread-Prüfer, dann verschwindet die Warnung. Schema-Editor


18
Ich halte das nicht für eine gute Idee. Hier liegt ein Problem vor, das der Thread-Prüfer entdeckt hat. Durch Deaktivieren der Thread-Überprüfung bleiben dieses und zukünftige Probleme unentdeckt und es entstehen zukünftige technische Schulden, um die Probleme zu beheben.
Ablarg

1
Mein Punkt ist, dass wir dies tun können, wenn wir OpenGL es-Rendering verwenden, da wir den Frame-Puffer im Haupt-Thread nicht rendern können. richtig?
L.Peng

1
Ah, wenn die Warnung nicht erscheint, besteht das Problem nicht?
Turing getestet

11
"Warum geht mein Rauchmelder weiter aus?" "Entfernen Sie einfach die Batterie, Problem gelöst."
John Montgomery

Wenn die Warnung nicht angezeigt wird, besteht das Problem nicht?
S. Gissel
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.