Obj-C __block-Variable behält das Verhalten bei

8

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:

%Vor%

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.

    
donalbain 15.06.2011, 19:11
quelle

2 Antworten

15

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:

%Vor%

Beachten Sie, dass __block nicht mehr benötigt wird, da Sie content nirgendwo innerhalb des Blocks zuweisen.

    
Jeremy W. Sherman 15.06.2011, 19:57
quelle
5

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 .

    
Jonathan Grynspan 15.06.2011 19:19
quelle