web-dev-qa-db-de.com

Diese Anwendung modifiziert die Autolayout-Engine von einem Hintergrund-Thread aus, was zu einer Beschädigung der Engine und zu seltsamen Abstürzen führen kann

Ich erhalte dieses Protokoll in der Konsole, wenn ich meine Anwendung in einem Simulator ausführte. Ich habe dies nicht in iOS 8 gesehen. Ich bin mir nicht ganz sicher, was das verursacht. Hat jemand anderes das gleiche Problem gefunden und wenn ja, wie wurde es behoben? oder gibt es irgendeine hilfe, die jemand in dieser Hinsicht leisten kann?

36

Ändern Sie die Benutzeroberfläche nicht von etwas anderem als dem Haupt-Thread. Während es auf einigen Betriebssystemen oder Geräten zu funktionieren scheint und nicht auf anderen, kann dies dazu führen, dass Ihre Anwendung instabil wird und unvorhersehbar abstürzt.

Wenn Sie auf eine Benachrichtigung antworten müssen, die can im Hintergrund erfolgt, müssen Sie sicherstellen, dass UIKit invocation im Haupt-Thread stattfindet.

Sie haben mindestens diese 2 Optionen:

Asynchroner Versand

Verwenden Sie GCD(Grand Central Dispatch), wenn Ihr Beobachter in einem Thread benachrichtigt werden kann. Sie können von jedem Thread aus zuhören und arbeiten und Änderungen in der Benutzeroberfläche in einem dispatch_async einschließen:

dispatch_async(dispatch_get_main_queue()) {
    // Do UI stuff here
}

Wann GCD verwenden? Wenn Sie nicht kontrollieren, wer die Benachrichtigung sendet. Dies kann das Betriebssystem, ein Cocoapod, eingebettete Bibliotheken usw. sein. Die Verwendung von GCD wird jedes Mal aktiviert. Nachteil: Sie müssen sich die Arbeit neu planen.


Hören Sie sich den Haupt-Thread an

Praktischerweise können Sie mit dem Parameter queue angeben, an welchen Thread der Beobachter benachrichtigt werden soll, zum Zeitpunkt der Registrierung für Benachrichtigungen.

addObserverForName:@"notification"
    object:nil
    queue:[NSOperationQueue mainQueue]
    usingBlock:^(NSNotification *note){
        // Do UI stuff here
    }

Wann im Hauptthread beachten? Wenn Sie sich registrieren und registrieren. Wenn Sie auf die Benachrichtigung antworten, sind Sie bereits da, wo Sie sein müssen.


Post-Benachrichtigung im Haupt-Thread

[self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];

Hybridlösung, die nicht garantiert dass der Beobachter nur von dieser Methode aus aufgerufen wird. Es ermöglicht einen leichteren Beobachter, dessen Kosten weniger robust sind. Nur hier als Lösung erwähnt sollten Sie wahrscheinlich vermeiden.

67
SwiftArchitect

Swift 3.0 

DispatchQueue.main.async {
}
20

Alle UI-Teil-Aktualisierungen, die Sie benötigen, um in den MAIN-Thread der App zu gelangen.

Ich rief ein createMenuView () in den Hintergrund und ich bekam einen Fehler

"Diese Anwendung ändert die Autolayout-Engine von einem Hintergrund-Thread aus, was zu einer Beschädigung der Engine und zu seltsamen Abstürzen führen kann"

Also rief ich die oben genannte Methode in den Main-Thread Using ein 

    DispatchQueue.main.async {
    }

in Swift 3.0 und Xcode 8.0

Korrigieren Sie den folgenden Code:

RequestAPI.post(postString: postString, url: "https://www.someurl.com") { (succeeded: Bool, msg: String, responceData:AnyObject) -> () in

        if(succeeded) {
            print(items: "User logged in. Registration is done.")

            // Move to the UI thread
            DispatchQueue.main.async (execute: { () -> Void in

                //Set User's logged in
                Util.set_IsUserLoggedIn(state: true)
                Util.set_UserData(userData: responceData)
                self.appDelegate.createMenuView()

            })

        }
        else {
            // Move to the UI thread
            DispatchQueue.main.async (execute: { () -> Void in
                let alertcontroller = UIAlertController(title: JJS_MESSAGE, message: msg, preferredStyle: UIAlertControllerStyle.alert)
                alertcontroller.title = "No Internet"
                alertcontroller.message = FAILURE_MESSAGE
                self.present(alertcontroller, animated: true, completion: nil)
            })
        }
    }
5
Anil Gupta

Sollte ein symbolischer Haltepunkt versuchen, das Problem zu erkennen: -  enter image description here

Symbol:

[UIView layoutIfNeeded]`

Bedingung:

!(BOOL)[NSThread isMainThread]

Dann fügen Sie Ihren UI Update-Code in den Haupt-Thread ein

DispatchQueue.main.async {}
3
Abdul Hameed

Sie haben Code, der das UI-Layout von einem Hintergrundthread aus aktualisiert. __ Die Änderung der Operationswarteschlange, in der Sie Ihren Code ausführen, muss nicht explizit sein. Zum Beispiel verwendet NSURLSession.shared () die Hauptwarteschlange nicht, wenn neue Anforderungen gestellt werden. Um sicherzustellen, dass Ihr Code im Hauptthread ausgeführt wird, verwende ich die statische Methode mainQueue () von NSOperationQueue.

Schnell:

NSOperationQueue.mainQueue().addOperationWithBlock(){
    //Do UI stuff here
}

Obj-C:

[NSOperationQueue mainQueue] addOperationWithBlock:^{
    //Do UI stuff here
}];
3
Nikolay

Das gleiche Problem ist in meinem Fall passiert, ich muss den Code folgendermaßen ändern, dann funktioniert es gut. Rufen Sie in ViewDidLoad diese Methode mit main thread Auf.

[self performSelectorOnMainThread:@selector(setUpTableRows) withObject:nil waitUntilDone:YES];
0
Preetha