Ich stoße auf ein merkwürdiges Problem, wenn ich versuche, auf eine Variable __block
(block mutable) von außerhalb eines Blocks zuzugreifen, in dem sie geändert wurde. Dies ist ein sehr praktisches Beispiel, das ich benutze, um Blöcke im Allgemeinen besser zu verstehen, aber derzeit habe ich einen Controller mit dieser Methode, der eine Zeichenfolge mit dem Inhalt von NSDictionary
erstellt, die NSDictionary
verwendet enumerateKeysAndObjectsUsingBlock:
Wenn ich diese Methode mit einem Wörterbuch verwende, das den Inhalt enthält:
%Vor% Die content
Variable wird innerhalb des Blocks korrekt geändert und ich erhalte diese Ausgabe mit jeder Iteration:
... Inhalt im Block:
%Vor%... Inhalt im Block:
%Vor%... Inhalt im Block:
%Vor% Sobald der Code jedoch aus dem Block austritt, wird durch den Zugriff auf die content
-Zeichenfolge EXC_BAD_ACCESS
zurückgegeben und bei einem Durchlauf scheint es, dass etwas Müllspeicher gedruckt wurde (kann nicht reproduziert werden) ...
Was bewirkt, dass diese Variable früh freigegeben wird? Ich hatte den Eindruck, dass die Definition von __block
bedeuten würde, dass sie beibehalten wird, wenn sie innerhalb eines Blocks verwendet und beim Verlassen des Blocks freigegeben wird. Aber die Variable bleibt erhalten und wird aufgrund des String-Literals automatisch freigegeben Ich erwarte, dass es erst nach dem frühesten Beenden dieser Methode freigegeben wird.
Das ist dein Problem:
%Vor% -stringByAppendingString:
gibt ein neues, automatisch freigegebenes Objekt zurück. Die Adresse dieses Objekts wird in content
gespeichert. Jeder durchläuft diese (implizite) Schleife - das heißt, jeder Aufruf des bereitgestellten Blocks - erzeugt ein brandneues Objekt und weist dann die Adresse dieses neuen Objekts content
zu. Keines dieser Objekte überlebt den enthaltenen Autorelease-Pool.
Was Sie tun sollten, ist die Verwendung von NSMutableString
und das direkte Anhängen von contentToAppend
an die veränderbare Zeichenkette. Zum Beispiel:
Beachten Sie, dass __block
nicht mehr benötigt wird, da Sie content
nirgendwo innerhalb des Blocks zuweisen.
Intern verwendet -enumerateKeysAndObjectsUsingBlock:
einen Autorelease-Pool. __block
scope-Objekte werden nach dem Ende der Lebensdauer des Blocks nicht beibehalten, sodass Sie ein Objekt im Blockbereich erstellen, das dann freigegeben wird, wenn der Autorelease-Pool des Wörterbuchs leer ist. Dies alles geschieht, bevor Sie versuchen, das Objekt zu drucken Wert von content
.
Tags und Links objective-c objective-c-blocks memory-management