Betrachten Sie diese Warnung:
self
stark in diesem Block wahrscheinlich ein Zyklus führen wird Capturing behalten
Wenn Sie die obige Warnung erhalten, sollten Sie Ihren Block für eine Bewertung
- alle expliziten Verweise auf
self
; oder
- alle impliziten Verweise auf
self
, die durch Referenzieren von Instanzvariablen verursacht werden.
Stellen wir uns vor, dass wir eine einfache Klasse Eigenschaft haben, dass ein Block war (dies wird die gleiche „behalten Zyklus“ Warnungen wie Ihre Frage erleben, aber meine Beispiele ein wenig einfacher halten):
@property (nonatomic, copy) void (^block)(void);
Und nehmen wir an, wir eine andere Klasse Eigenschaft hatten wir in unserem Block verwenden wollte:
@property (nonatomic, strong) NSString *someString;
Wenn Sie innerhalb des Blocks (in meinem Beispiel unten in Prozess der Zugriff auf diese Eigenschaft), Sie verweisen self
wird natürlich erhalten, dass über die behalten Zyklus Risikowarnung:
self.block = ^{
NSLog(@"%@", self.someString);
};
, die über das Muster behoben wird vorgeschlagen, dass Sie, und zwar:
__weak typeof(self) weakSelf = self;
self.block = ^{
NSLog(@"%@", weakSelf.someString);
};
Weniger offensichtlich, werden Sie auch die „Zyklus behalten“ erhalten Warnung, wenn Sie verweisen auf ein Instanzvariable der Klasse innerhalb des Blocks, zum Beispiel:
self.block = ^{
NSLog(@"%@", _someString);
};
Dies, da die _someString
Instanzvariable trägt eine implizite Referenz zu self
, und ist eigentlich äquivalent zu:
self.block = ^{
NSLog(@"%@", self->_someString);
};
Sie geneigt sein könnte, um zu versuchen schwache Selbstmuster zu übernehmen hier auch, aber man kann es nicht.Wenn Sie die weakSelf->_someString
Syntaxmuster versuchen, wird die Compiler Sie darüber warnen:
Dereferenzierung eines __weak
Zeiger nicht wegen möglichem Nullwert durch Racebedingung verursachte erlaubt ist, weist es strong
variable erste
Sie lösen damit diese durch die weakSelf
Muster verwenden, sondern auch ein lokales strong
Variable innerhalb des Blockes erstellen und verwenden zu dereferenzieren den Instanzvariable:
__weak typeof(self) weakSelf = self;
self.block = ^{
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"%@", strongSelf->_someString);
// or better, just use the property
//
// NSLog(@"%@", strongSelf.someString);
}
};
Nebenbei, diese Erstellung einer lokalen strong
Referenz, strongSelf
, innerhalb des Blocks hat auch andere Vorteile, nämlich, wenn der Abschlussblock asynchron auf einem anderen Thread ausgeführt wird, müssen Sie sich keine Gedanken über self
sein Die Zuweisung wird aufgehoben, während der Block ausgeführt wird, was zu unbeabsichtigten Konsequenzen führt.
Diese weakSelf
/strongSelf
Muster ist sehr nützlich, wenn sie mit Blockeigenschaften zu tun, und Sie wollen verhindern, dass Zyklen beibehalten (auch bekannt als starke Referenzzyklen), aber zugleich sichergestellt wird, dass self
nicht in der Mitte der Ausführung der ausgeplant werden Abschlussblock.
FYI, diskutiert Apple dieses Muster in der "nicht trivialen Zyklen" -Diskussion weiter unten im Use Lifetime Qualifiers to Avoid Strong Reference Cycles Abschnitt der Transitioning to ARC Release Notes.
Sie berichten, dass Sie einige „Fehler“ erhalten, wenn Sie weakSelf.generalInstaImage
in Ihrem Beispiel verwiesen. Dies ist der richtige Weg, um diese "Retain Cycle" Warnung zu lösen. Wenn Sie also eine Warnung erhalten haben, sollten Sie diese mit uns teilen und uns zeigen, wie Sie die Eigenschaft deklariert haben.
Was ist der Fehler? versuchen Sie es mit 'ID' oder dem tatsächlichen Klassennamen anstelle von' typeof (self) ' – Fonix