Mit schwachen selbst in dispatch_async Funktion
Lese ich viele Beiträge über die Verwendung __weak self
innen dispatch_async
und jetzt bin ich ein litle bisschen verwirrt.
wenn ich :
self.myQueue = dispatch_queue_create("com.biview.core_data", NULL);
dispatch_async(self.myQueue, ^(void){
if (!self.var1) {
self.var1 = ...;
}
dispatch_async(dispatch_get_main_queue(), ^(void) {
if ([self.var2 superview]) {
[self.var2 removeFromSuperview];
}
[self.Label setText:text];
});
});
brauche ich __weak self
. Da ich gelesen habe, dass in einigen Fällen dispatch_async
müssen nicht eine __weak self
.
Siehe den letzten Kommentar hier
InformationsquelleAutor der Frage Marko Zadravec | 2014-02-24
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vorausgesetzt, selbst ist ein Zeiger auf ein Objekt, um eine
UIViewController
.Dinge zu beachten:
Einen
UIViewController
ist ein "UIKit" - Objekt. UIKit Gegenstände dürfen nicht gesendet werden Methoden, die auf nicht-Haupt-threads, das ist - diese Methoden müssen auf dem primären thread ausgeführt nur!Einen block, wurde in die Warteschlange eingereiht in eine Warteschlange - ob synchron oder asynchron - werden schließlich ausgeführt -- egal was! Gut, wenn das Programm beendet wird, bevor dies geschehen kann.
Erfasst retainable starke Zeiger werden beibehaltenwenn der block kopiert werden (zum Beispiel, wenn asynchron ausgelöst), und wieder veröffentlichtwenn der block zerstört wird (nachdem es fertig ist).
Erfasst retainable schwach Zeiger werden NICHT gespeichert und nicht veröffentlicht.
In Ihrem Szenario, wo Sie erfassen selbst in den block, das ausgelöst wird, auf die main queueSie brauchen keine sorgen zu machen, dass schlimme Dinge passieren.
So, warum? Und was passiert tatsächlich?
Seit selbst werden erfasst in den block, die ausgelöst wird asynchronselbst implizit beibehaltenund veröffentlicht wieder, wenn der block fertig ist.
Das bedeutet, die Lebens-Zeit von selbst werden erweitert bis nach dem block beendet. Beachten Sie, dass Ihre zweiten block ausgelöst, auf die Haupt-threadund es ist garantiert, dass selbst ist noch am Leben, wenn der block ausgeführt wird.
Diese "extended life" vor, könnte eine gewünschte Funktion von Ihrem Programm.
Wenn Sie explizit will nicht verlängern die Lebensdauer der
UIViewController
Objekt, und stattdessen wollen die block - als es schließlich ausgeführt wird - überprüfenob dieseUIViewController
Objekt noch vorhanden ist, können Sie mit einer __weak pointer von selbst. Beachten Sie, dass der block wird schließlich ausgeführt, egal ob dieUIViewController
ist noch am Leben oder wurde freigegeben in der Zwischenzeit.Möchten Sie vielleicht den block tun "nichts", wenn die
UIViewController
wurde freigegeben vor der block wird ausgeführt:Siehe auch: Der übergang zum ARC Release Notes
Denken Sie daran:
UIKit
Objekte wird nicht gesendet Methoden auf nicht-Haupt-threads!Einer anderen subtilen Fehler kann auftreten, tun, um die Tatsache, dass
UIKit
Objekte sind Methoden ausführen, nur auf dem Haupt-thread.Dieser kann verletzt sein, wenn ein block fängt ein
UIKit
Objekt, das asynchron ausgelöst, und führt auf eine nicht-Haupt - thread. Dann kann es passieren, dass der block hält die letzten starken Hinweis auf, dassUIKit
Objekt. Nun, wenn der block wird schließlich ausgeführt, wird der block zerstört, und derUIKit
Objekt freigegeben wird. Da dies die Letzte starke Verweis auf dieUIKit
Objekt, wird es freigegeben. Dies geschieht jedoch auf den thread, in dem der block ausgeführt wurde - und dies ist nicht der Haupt-thread! Nun, schlimme Dinge können (und werden normalerweise) passieren kann, da diedealloc
Methode ist immer noch eine Methode, an einenUIKit
Objekt.Können Sie diesen Fehler vermeiden, durch die Entsendung von einem block erfassen einen starken Zeiger auf das UIKit-Objekt, und senden Sie eine dummy-Methode:
In Ihrem Szenario obwohl, die Letzte starke Referenz werden könnte, nur in dem block, der ausgeführt wird auf dem Haupt-thread. Ja, sind Sie sicher von dieser subtilen Fehler. 😉
Edit:
In Ihrem setup, Sie haben nie einen retain-Zyklus. Ein retain-Zyklus tritt auf, wenn ein retainable Objekt stark auf ein anderes retainable Objekt B und Objekt B dringend Referenzen A. Beachten Sie, dass ein "Block" ist auch ein retainable Objekt.
Ein erfundenes Beispiel mit einer zyklischen Referenz:
Hier, wir haben eine Eigenschaft, die Abschlussderen Wert Typ ist ein Block. Das heißt, wir bekommen ein ivar mit dem Namen
_completion
deren Typ ein Block.Client kann einen completion handler, die aufgerufen werden soll, wenn eine bestimmte operation abgeschlossen hat. Angenommen, der Betrieb holt sich eine Liste von Benutzern von einem remote-server. Der plan ist, setzen Sie die Eigenschaft Benutzer sobald die operation beendet:
Den unvorsichtigen Ansatz könnte versehentlich die Einführung einer zyklischen Referenz:
Irgendwo in "UsersViewController.m"
Hier selbst hat einen starken Bezug auf die ivar
_completion
das ist ein block. Und der block selbst erfasst selbstdie Ursachen zu behalten selbstwenn der block wird kopiert, wenn es ausgelöst wird. Dies ist eine klassische Referenz-Zyklus.Um zu vermeiden, dass die zyklische Referenz, haben wir ein paar alternativen:
Mit einem
__weak
qualifizierte Zeiger der selbstMit einem
__block
qualifizierte Zeiger der selbst und schließlich esnil
im block, wenn es fertig ist:Siehe auch: Der übergang zum ARC Release Notes
InformationsquelleAutor der Antwort CouchDeveloper
Swift-update:
Ein Beispiel für diese so genannte stark-schwach-Tanz in swift:
Beliebte open-source-Projekt
Alamofire
verwendet diesen Ansatz.Für mehr info check out swift-style-guide
Swift 3-update:
InformationsquelleAutor der Antwort Warif Akhand Rishi