Dieser Fehler ist in meinem OS X häufig mit swift aufgetreten:
"Diese Anwendung ändert die Autolayout-Engine von einem Hintergrund-Thread aus, was zu einer Beschädigung der Engine und seltsamen Abstürzen führen kann. Dies wird in einer zukünftigen Version eine Ausnahme verursachen."
Ich habe ein NSWindow und tausche die Ansichten zum contentView
Fenster aus. Ich erhalte die Fehlermeldung, wenn ich versuche, eine NSApp.beginSheet
im Fenster auszuführen, oder wenn ich eine subview
zum Fenster hinzufüge . Ich habe versucht, die automatische Größenänderung zu deaktivieren, und ich habe nichts, was das automatische Layout verwendet. Irgendwelche Gedanken?
Manchmal ist es in Ordnung und nichts passiert, manchmal bricht es mich total UI
und nichts wird geladen
quelle
Antworten:
Es muss in einem anderen Thread platziert werden, damit die Benutzeroberfläche aktualisiert werden kann, sobald die Ausführung der Thread-Funktion abgeschlossen ist:
Modern Swift:
Ältere Versionen von Swift vor Swift 3.
Ziel c:
quelle
Beim Debuggen mit print-Anweisungen ohne Verwendung von 'dispatch_async' wird eine ähnliche Fehlermeldung angezeigt. Wenn Sie diese Fehlermeldung erhalten, ist es an der Zeit, sie zu verwenden
Swift 4
Swift 3
Frühere Swift-Versionen
quelle
dispatch_async(dispatch_get_main_queue(), ^{ /* UI related code */ });
Bearbeiten: Ich habe seine Antwort aktualisiert, die Syntaxformatierung funktioniert dort besser.Der Fehler "Diese Anwendung ändert die Autolayout-Engine von einem Hintergrund-Thread aus" wird lange nach dem eigentlichen Problem in der Konsole protokolliert. Daher kann das Debuggen ohne Verwendung eines Haltepunkts schwierig sein.
Ich habe die Antwort von @ markussvensson verwendet, um mein Problem zu erkennen, und habe sie mithilfe dieses symbolischen Haltepunkts gefunden (Debug> Haltepunkte> Symbolischen Haltepunkt erstellen):
[UIView layoutIfNeeded]
oder[UIView updateConstraintsIfNeeded]
!(BOOL)[NSThread isMainThread]
Erstellen und führen Sie die App auf dem Emulator aus und replizieren Sie die Schritte, die dazu führen, dass die Fehlermeldung ausgegeben wird (die App ist langsamer als gewöhnlich!). Xcode stoppt dann die App und markiert die Codezeile (z. B. den Aufruf einer Funktion), die über einen Hintergrund-Thread auf die Benutzeroberfläche zugreift.
quelle
movq 0x10880ba(%rip), %rsi ; "_wantsReapplicationOfAutoLayoutWithLayoutDirtyOnEntry:"
Wenn Sie versuchen, einen Textfeldwert zu aktualisieren oder eine Unteransicht in einem Hintergrundthread hinzuzufügen, kann dieses Problem auftreten. Aus diesem Grund sollten Sie diese Art von Code in den Hauptthread einfügen.
Sie müssen Methoden, die UI-Updates aufrufen, mit dispatch_asynch umschließen, um die Hauptwarteschlange abzurufen. Zum Beispiel:
EDITIERT - SWIFT 3:
Jetzt können wir das mit dem nächsten Code tun:
quelle
Für mich stammt diese Fehlermeldung von einem Banner aus dem Admob SDK.
Ich konnte den Ursprung zu "WebThread" verfolgen, indem ich einen bedingten Haltepunkt festlegte.
Dann konnte ich das Problem beseitigen, indem ich die Bannererstellung mit folgenden Informationen einkapselte:
Ich weiß nicht, warum dies geholfen hat, da ich nicht sehen kann, wie dieser Code von einem Nicht-Haupt-Thread aufgerufen wurde.
Hoffe es kann jedem helfen.
quelle
Ich hatte dieses Problem seit dem Update auf das iOS 9 SDK, als ich einen Block aufrief, der UI-Updates in einem asynchronen NSURLConnection-Anforderungsabschluss-Handler durchführte. Das Problem wurde behoben, indem der Blockaufruf mit dispatch_main_queue in dispatch_async eingefügt wurde.
In iOS 8 hat es gut funktioniert.
quelle
Hatte das gleiche Problem, weil ich verwendet habe
performSelectorInBackground
.quelle
Sie dürfen die Benutzeroberfläche nicht außerhalb des Hauptthreads ändern! UIKit ist nicht threadsicher, so dass das obige Problem und auch einige andere seltsame Probleme auftreten, wenn Sie dies tun. Die App kann sogar abstürzen.
Um die UIKit-Operationen auszuführen, müssen Sie den Block definieren und ihn in der Hauptwarteschlange ausführen lassen: z.
quelle
Offensichtlich führen Sie ein UI-Update für den Hintergrundthread durch. Kann nicht genau vorhersagen, wo, ohne Ihren Code zu sehen.
Dies sind einige Situationen, in denen dies passieren kann:
Möglicherweise machen Sie etwas im Hintergrund-Thread und verwenden es nicht. In derselben Funktion ist dieser Code leichter zu erkennen.
Aufrufen einer Funktion, die einen Webanforderungsaufruf für den Hintergrundthread ausführt, und dessen Vervollständigungshandler, der eine andere Funktion aufruft, die ein UI-Update ausführt. Um dieses Problem zu lösen, überprüfen Sie den Code, in dem Sie die Benutzeroberfläche nach dem Webrequest-Aufruf aktualisiert haben.
quelle
Das Hauptproblem bei "Diese Anwendung ändert die Autolayout-Engine aus einem Hintergrund-Thread" besteht darin, dass sie anscheinend lange nach dem eigentlichen Problem protokolliert wird. Dies kann die Fehlerbehebung sehr schwierig machen.
Ich habe es geschafft, das Problem zu lösen, indem ich drei symbolische Haltepunkte erstellt habe.
Debug> Haltepunkte> Symbolischen Haltepunkt erstellen ...
Haltepunkt 1:
Symbol:
-[UIView setNeedsLayout]
Bedingung:
!(BOOL)[NSThread isMainThread]
Haltepunkt 2:
Symbol:
-[UIView layoutIfNeeded]
Bedingung:
!(BOOL)[NSThread isMainThread]
Haltepunkt 3:
Symbol:
-[UIView updateConstraintsIfNeeded]
Bedingung:
!(BOOL)[NSThread isMainThread]
Mit diesen Haltepunkten können Sie leicht eine Unterbrechung in der tatsächlichen Zeile erhalten, in der Sie UI-Methoden für Nicht-Hauptthread falsch aufrufen.
quelle
Ich hatte dieses Problem beim erneuten Laden von Daten in UITableView. Durch einfaches Versenden des Nachladens wie folgt wurde das Problem für mich behoben.
quelle
Ich hatte das gleiche Problem. Es stellte sich heraus,
UIAlerts
dass ich die Hauptwarteschlange benötigte. Aber sie sind veraltet .Als ich das
UIAlerts
auf das änderteUIAlertController
, hatte ich das Problem nicht mehr und musste keinendispatch_async
Code verwenden. Die Lektion - achten Sie auf Warnungen. Sie helfen auch dann, wenn Sie es nicht erwarten.quelle
Sie haben bereits die richtige Code-Antwort von @Mark, aber nur um meine Ergebnisse zu teilen: Das Problem ist, dass Sie eine Änderung in der Ansicht anfordern und davon ausgehen, dass dies sofort geschehen wird. In der Realität hängt das Laden einer Ansicht von den verfügbaren Ressourcen ab. Wenn alles schnell genug geladen wird und es keine Verzögerungen gibt, bemerken Sie nichts. In Szenarien, in denen es aufgrund des ausgelasteten Prozessthreads usw. zu Verzögerungen kommt, gerät die Anwendung in eine Situation, in der etwas angezeigt werden soll, obwohl es noch nicht bereit ist. Daher ist es ratsam, diese Anforderungen in asynchronen Warteschlangen zu versenden, damit sie basierend auf der Last ausgeführt werden.
quelle
Ich hatte dieses Problem, als ich TouchID verwendete. Wenn dies jemand anderem hilft, verpacken Sie Ihre Erfolgslogik, die wahrscheinlich etwas mit der Benutzeroberfläche in der Hauptwarteschlange zu tun hat.
quelle
Dies kann so einfach sein wie das Festlegen eines Textfeld- / Beschriftungswerts oder das Hinzufügen einer Unteransicht innerhalb eines Hintergrundthreads, wodurch sich das Layout eines Felds ändern kann. Stellen Sie sicher, dass alles, was Sie mit der Schnittstelle tun, nur im Hauptthread geschieht.
Überprüfen Sie diesen Link: https://forums.developer.apple.com/thread/7399
quelle
Ich hatte das gleiche Problem beim Versuch, die Fehlermeldung in UILabel im selben ViewController zu aktualisieren (es dauert eine Weile, bis die Daten aktualisiert sind, wenn ich dies mit normaler Codierung versuche). Ich habe
DispatchQueue
in Swift 3 Xcode 8 verwendet und es funktioniert.quelle
Wenn Sie diesen Fehler beheben möchten, aktivieren Sie das Kontrollkästchen Hauptthread-Prüfer bei Problemen. Es ist meistens einfach, das Problem zu beheben, indem die problematische Zeile in der Hauptwarteschlange versandt wird.
quelle
Für mich war das Problem das Folgende. Stellen Sie sicher, dass
performSegueWithIdentifier:
der Haupt-Thread ausgeführt wird:quelle
Swift 4,
Angenommen, Sie rufen eine Methode mithilfe der Operationswarteschlange auf
Angenommen, die Funktion searchFavourites lautet wie folgt:
Wenn Sie den gesamten Code in der Methode "searchFavourites" im Hauptthread aufrufen, wird immer noch ein Fehler ausgegeben, wenn Sie eine Benutzeroberfläche darin aktualisieren.
Also Lösung verwenden,
Für diese Art von Szenario.
quelle
Hier sehen Sie sich diese Zeile aus den Protokollen an
Sie können überprüfen, welche Funktion vom Hintergrundthread aus aufgerufen wird oder wo Sie die API-Methode aufrufen, um Ihre Funktion vom Hauptthread aus wie folgt aufzurufen.
Loggt hier
quelle
Ich bin auch auf dieses Problem gestoßen, als eine Menge dieser Nachrichten und Stapelspuren in der Ausgabe gedruckt wurden, als ich die Größe des Fensters auf eine kleinere Größe als den Anfangswert geändert habe. Ich verbrachte eine lange Zeit damit, das Problem herauszufinden, und dachte, ich würde die ziemlich einfache Lösung teilen. Ich hatte einmal
Can Draw Concurrently
auf einemNSTextView
durch IB aktiviert . Dadurch wird AppKit mitgeteilt, dass die Ansichtsmethodedraw(_:)
von einem anderen Thread aus aufgerufen werden kann . Nach dem Deaktivieren wurden keine Fehlermeldungen mehr angezeigt. Vor dem Update auf macOS 10.14 Beta gab es keine Probleme, aber gleichzeitig habe ich auch begonnen, den Code zu ändern, um die Arbeit mit der Textansicht auszuführen.quelle