Wie kann in ARC-fähigem Code eine Warnung über einen möglichen Aufbewahrungszyklus behoben werden, wenn eine blockbasierte API verwendet wird?
Die Warnung:
Capturing 'request' strongly in this block is likely to lead to a retain cycle
produziert von diesem Codeausschnitt:
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...
[request setCompletionBlock:^{
NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.rawResponseData error:nil];
// ...
}];
Die Warnung hängt mit der Verwendung des Objekts request
innerhalb des Blocks zusammen.
responseData
stattdessenrawResponseData
die ASIHTTPRequest-Dokumentation verwenden.Antworten:
Ich antworte mir:
Mein Verständnis der Dokumentation besagt, dass die Verwendung des Schlüsselworts
block
und das Setzen der Variablen auf Null nach der Verwendung innerhalb des Blocks in Ordnung sein sollte, aber die Warnung weiterhin angezeigt wird.Update: Es funktioniert mit dem Schlüsselwort '_ schwach' anstelle von ' _block' und unter Verwendung einer temporären Variablen:
Wenn Sie auch auf iOS 4 abzielen möchten, verwenden Sie
__unsafe_unretained
anstelle von__weak
. Gleiches Verhalten, aber der Zeiger bleibt baumeln, anstatt automatisch auf Null gesetzt zu werden, wenn das Objekt zerstört wird.quelle
Das Problem tritt auf, weil Sie der Anforderung einen Block zuweisen, der einen starken Verweis auf die Anforderung enthält. Der Block behält die Anforderung automatisch bei, sodass die ursprüngliche Anforderung aufgrund des Zyklus nicht freigegeben wird. Sinn ergeben?
Es ist nur seltsam, weil Sie das Anforderungsobjekt mit __block markieren, damit es auf sich selbst verweisen kann. Sie können dies beheben, indem Sie eine schwache Referenz daneben erstellen .
quelle
Es verursacht aufgrund des Haltens des Selbst im Block. Auf den Block wird von self aus zugegriffen, und auf self wird im Block verwiesen. Dadurch wird ein Aufbewahrungszyklus erstellt.
Versuchen Sie, dies zu lösen, indem Sie eine schwache Referenz von erstellen
self
quelle
Manchmal hat der xcode-Compiler Probleme bei der Identifizierung der Aufbewahrungszyklen. Wenn Sie also sicher sind, dass Sie den CompletionBlock nicht beibehalten, können Sie ein Compiler-Flag wie folgt setzen:
quelle
Wenn ich die von Guillaume bereitgestellte Lösung ausprobiere, ist im Debug-Modus alles in Ordnung, im Release-Modus stürzt sie jedoch ab.
Beachten Sie, dass Sie nicht __weak, sondern __unsafe_unretained verwenden, da mein Ziel iOS 4.3 ist.
Mein Code stürzt ab, wenn setCompletionBlock: für das Objekt "request" aufgerufen wird: request wurde freigegeben ...
Diese Lösung funktioniert also sowohl im Debug- als auch im Release-Modus:
quelle
Was ist der Unterschied zwischen __schwacher und __blocker Referenz?
quelle
Schauen Sie sich die Dokumentation auf der Apple-Entwickler-Website an: https://developer.apple.com/library/prerelease/ios/#documentation/General/Conceptual/ARCProgrammingGuide/Introduction.html#//apple_ref/doc/uid/TP40011029
Am Ende der Seite befindet sich ein Abschnitt über Aufbewahrungszyklen.
quelle