Ich wurde diese Frage in einem Interview gestellt. Ich möchte wissen, was der Fall sein wird, wenn wir Hintergrund Thread UILabel
geben.Was passiert, wenn wir UIlabel dem Hintergrund-Thread in GCD oder NSOperationQueue geben
Antwort
Die kurze Antwort ist "Ergebnisse sind undefiniert" oder "Schlechte Dinge". UIKit ist nicht Thread-sicher, also weißt du es nicht, aber es wird nicht gut.
Ich habe gesehen, Änderungen an der Benutzeroberfläche nehmen eine LOOOOOONNNG Zeit, wenn überhaupt, und ich habe Abstürze gesehen.
Die bessere Antwort ist "Tu das nicht."
In ios 9 erhalten Sie eine Ausnahme, wenn Sie UI-Elemente in einem anderen Thread ändern – Paulw11
@ Paulw11, Wirklich? Garantiert? Was ist der Mechanismus, der eine Ausnahme auslöst? –
Sie erhalten eine Ausnahmebedingungsnachricht, die besagt "Sie ändern die Benutzeroberfläche in einem Hintergrundthread" – Paulw11
Es hängt davon ab, ob das Label in der View-Hierarchie ist oder nicht. Allgemeine Regel ist, dass der Code, der von einem Hintergrund-Thread ausgeführt wird, keine UI-Updates wie view.addSubview
oder label.setNeedsLayout
etc. auslösen sollte, dann ist es sicher, mit Ihrem Label in diesem Thread herumzuspielen.
Sie sollten jedoch vorsichtig sein, sobald Etikett zu einer Ansicht hinzugefügt wird, ist sogar die Aktualisierung label.text
in einem Hintergrund Thread gefährlich, da es das Superview-Layout ungültig wird, so dass die Benutzeroberfläche in diesem Thread aktualisiert wird.
Ihre benutzerdefinierte UILabel Klasse sagen Lassen Sie einige Zeit tut in seinem Konstruktor aufwendige Operation, die nichts mit dem UI zu tun hat:
class MyFatLabel: UILabel {
override init(frame: CGRect) {
super.init(frame: frame)
self.text = "Lorem ipsum"
self.readDataFromDisk() // will block the main thread.
}
}
Dann können Sie dieses Label in einem separaten Thread initialisieren und fügen Sie in eine Ansicht in der Haupt (UI) Thread so die Interaktion des Benutzers mit der Benutzeroberfläche wird nicht blockiert werden:
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
let label = MyFatLabel(frame: CGRectZero)
dispatch_async(dispatch_get_main_queue()) {
view.addSubview(label)
}
}
Lange Rede kurzen Sinn, können Sie neue UILabel initialisieren (oder jeden UIResponder) in einem Hintergrund-Thread Sie jedoch, sollte irgendeine seiner Eigenschaften ändern, die UI-Aktualisierung auslösen tes innerhalb des Hauptthreads.
Ich glaube, UI-Elemente sollten nur auf dem Haupt-Thread geändert werden. http://StackOverflow.com/a/7905497/4475605 – Adrian
Es hängt davon ab, was Sie mit dem 'UILabel' versuchen. – rmaddy