iOS-Blöcke und starke / schwache Referenzen auf sich selbst
Ich habe eine Frage über starke und schwache Referenzen, um sich selbst in Blöcken in iOS. Ich weiß, den richtigen Weg zu finden, um sich selbst in einen block zu schaffen, ist ein schwacher Verweis außerhalb des Blocks, und dann einen starken Hinweis auf, dass die schwache Referenz innerhalb des Blocks, so wie hier:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^ {
typeof(self) strongSelf = weakSelf;
NSLog(@"%@", strongSelf.someProperty);
});
Jedoch, was passiert, wenn Sie verschachtelte Blöcke? Ist die eine Reihe von Referenzen genug? Oder benötigen Sie einen neuen Satz für jeden block? Zum Beispiel, welche der folgenden ist richtig?
:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^ {
typeof(self) strongSelf = weakSelf;
NSLog(@"%@", strongSelf.someProperty);
dispatch_async(dispatch_get_main_queue(), ^ {
strongSelf.view.frame = CGRectZero;
});
});
Oder so:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^ {
typeof(self) strongSelf = weakSelf;
NSLog(@"%@", strongSelf.someProperty);
__weak typeof(strongSelf) weakSelf1 = strongSelf;
dispatch_async(dispatch_get_main_queue(), ^ {
typeof(strongSelf) strongSelf1 = weakSelf1;
strongSelf1.view.frame = CGRectZero;
});
});
Jede information oder Erklärung sehr dankbar!
InformationsquelleAutor der Frage Mason | 2013-09-26
Du musst angemeldet sein, um einen Kommentar abzugeben.
Brauchen Sie nicht, um zwei Sätze von schwachen Referenzen. Was Sie wollen vermeiden, mit den Blöcken ist eine retain-Zyklus—zwei Objekte halten sich gegenseitig am Leben unnötig.
Wenn ich ein Objekt mit dieser Eigenschaft:
und ich habe diese Methode:
wird der block am Leben gehalten werden, wenn ich speichern Sie es in den
completionBlock
Eigenschaft. Aber da es Referenzenself
im block, wird der block haltenself
am Leben bis es Weg geht—aber das wird nicht passieren, da sind Sie beide auf jede andere.In dieser Methode:
brauchen Sie nicht, um eine schwache Referenz zu
self
. Der block wird haltenself
am Leben, da es Referenzenself
aus, aber da alles, was wir tun, ist die übergabe der block Weg zu[NSOperationQueue mainQueue]
self
ist nicht zu halten den block lebendig.Hoffe, das hilft.
InformationsquelleAutor der Antwort Jeff Kelley
Beide Konstrukte sind in Ordnung. Es kommt nur auf deine Absicht. Was wollen Sie passieren, wenn das Objekt (a) veröffentlicht, nachdem der äußere block beginnt aber (b) vor dem inneren block beginnt auf der Haupt-queue? Wenn Sie nicht wollen, es bleibt in diesem Szenario (die ich vielleicht erraten war Ihre Absicht, da man durch diese
weakSelf
übung in den ersten Platz), dann nutzen Sie Ihre Letzte Beispiel, wo Sie den schwachen zweiten Zeiger. Ansonsten können Sie mit Ihrem anderen Beispiel.Gesagt haben, dass, ein paar Beobachtungen:
Ist es nicht einen Abschluss verzichtet, die Sie haben, um mit dieser
weakSelf
Muster in den ersten Platz. Einige Leute denken fälschlicherweise, dass Sie haben Verwendung dieserweakSelf
Muster zu vermeiden, die eine starke Referenz-Zyklus (ein.k.ein. retain-Zyklus). Aber in diesem code-Beispiel nicht als eine starke Referenz-Zyklus. Es ist einfach behält sich das Objekt, während die gelieferte code ausgeführt wird, die eine sehr unterschiedliche Berücksichtigung.In der Tat, manchmal Sie brauchen/wollen. Manchmal tun Sie nicht. Es hängt von der business problem Sie zu lösen. Absolut, Sie oft nicht wollen, es zu halten, die einen starken Bezug zur
self
in welchem Fall dieweakSelf
Muster macht auch Sinn. Aber das ist nicht immer der Fall.Aber mein Punkt ist, dass Sie sollten nicht verfolgen diese
weakSelf
Muster (zumindest in diesemdispatch_async
Szenario) zu vermeiden, eine starke Referenz-Zyklus. Kein Zyklus existiert. Wo dies ein Problem ist, wo Sie einen block variable (z.B. einigecompletionHandler
block). In diesem Fall, dieweakSelf
Muster ist entscheidend. Aber nicht hier.Aber lasst uns für einen Moment das Szenario, in dem Sie nicht möchten, dass
self
beibehalten. Dann gibt es eine Frage, ob Sie möchten, dass der versandt code weiterhin in den ersten Platz. Wenn nicht, solltest du vielleicht über eine operation queue mit Abbrechbare Vorgänge statt den GCD.Zum Beispiel, ich bin erstaunt, wie oft Leute zerbrechen sich den Kopf darüber, ob Sie gehen, behalten Sie die Ansicht-controller, während einige hintergrund-Netzwerk-Anfrage ausgeführt wird, aber Mach dir keine sorgen darüber, ob Sie sollten das Abbrechen, das hintergrund-Netzwerk Anfrage in den ersten Platz. Oft, letzteres ist weitaus wichtiger design-Rücksicht (z.B. PDF-oder Bild, das Sie herunterladen dauert bis weit mehr system-Ressourcen (Speicher-und Netzwerk-Bandbreite) als die view-controller das jemals wird).
Aber nehmen wir an, dass (a) Sie wirklich wollen, das ausgelöst wird der code weiter ausgeführt werden, sondern (b) Sie nicht behalten wollen
self
. (Dies scheint wie ein Seltenes Szenario, aber es ist die, die Sie haben gefragt, also lassen Sie uns verfolgen.) Die abschließende Frage, ob Sie IhrestrongSelf
Konstrukt, auch. In deinem Fall, wo du nur den Aufruf einer einzigen Methode derself
Sie brauchen nicht die Mühe mit diesemstrongSelf
konstruieren. Das ist entscheidend, nur, wenn Sie gehen, um Rücksicht ivars oder anderweitig benötigen, um Wettlaufsituationen zu vermeiden. Aber, in diesem Beispiel gegeben, dass eine Nachricht gesendet, um einenil
Objekt tut nichts, Sie technisch oft nicht brauchen, um über diesestrongSelf
Konstrukt überhaupt.Versteh mich nicht falsch. Es ist gut, um die Arme um den
weakSelf
- Muster, sowie die verschachteltestrongSelf
Muster, die manchmal begleitet Sie. Ich bin nur darauf hindeutet, es ist gut zu verstehen, wenn diese Muster sind Sie wirklich nötig sind. Und ich denke, dass die Wahl der GCD im Vergleich zu einem stornierbarNSOperation
ist oft ein weit mehr kritische, aber oft übersehen, eine Frage stellen.InformationsquelleAutor der Antwort Rob
Blöcke erzeugt und auf dem stack gespeichert werden. So wird der block zerstört werden, wenn die Methode, erstellt den block zurück.
Wenn ein block wird zu einer Instanz-variable ARC kopieren Sie den block vom stack auf den heap. Sie können explizit einen block kopieren mit der copy-Nachricht. Ihr block ist nun eine heap-basierte block statt einer stack-basierten block. Und Sie haben sich mit einigen Speicher-management-Probleme. Der block selbst wird eine starke Referenz auf alle Objekte, auf die Sie verweisen. Erklären __weak-Pointer außerhalb des Blocks und dann die Bezugnahme auf diesen Zeiger innerhalb des Blocks zu vermeiden, behalten Zyklen.
InformationsquelleAutor der Antwort user3378170