2013-01-22 4 views
7

Ich habe derzeit Probleme, die Grundlagen von Obj-C-Blöcken und den __block-Speichertyp zu verstehen. Aus der folgenden Dokumentation:Probleme beim Verständnis der Objective-C-Block-Dokumentation

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6

Ich versuche, den folgenden Absatz und Beispiele zu verstehen:

Wenn ein Block kopiert wird, erstellt es starke Referenzen Variablen innerhalb der verwendeten Objekt Block. Wenn Sie innerhalb der Implementierung einer Methode einen Block verwenden:

Wenn Sie auf eine Instanzvariable als Referenz zugreifen, wird ein starker Verweis auf self gemacht; Wenn Sie auf eine Instanzvariable nach Wert zugreifen, wird auf die Variable stark Bezug genommen. Die folgenden Beispiele erläutern die beiden unterschiedlichen Situationen:

dispatch_async(queue, ^{ 
    // instanceVariable is used by reference, a strong reference is made to self 
    doSomethingWithObject(instanceVariable); 
}); 

id localVariable = instanceVariable; 
dispatch_async(queue, ^{ 
    /* 
     localVariable is used by value, a strong reference is made to localVariable 
     (and not to self). 
    */ 
    doSomethingWithObject(localVariable); 
}); 

dieses Verhalten für eine bestimmte Objektvariable außer Kraft zu setzen, können Sie es mit dem __block Speichertyp Modifikator markieren.

Meine Fragen:

  1. Wie genau ist ein Beispiel von „Verweis zugegriffen“, während der andere durch die Variable zugegriffen wird? Warum wird localVariable "nach Wert verwendet?"
  2. Was bedeutet das Dokument, wenn "ein starker Hinweis auf sich selbst gemacht wird"? Auf welches "Selbst" bezieht es sich?
  3. Wenn ich den __block-Speichertyp im zweiten Beispiel zu localVariable hinzufüge, kann ich nicht davon ausgehen, dass der Block über die Variable geschlossen wird, sodass sie im Heap bleibt, bis der Block freigegeben wird? Welche anderen Dinge passieren?

Vielen Dank!

Antwort

6

Wie genau wird ein Beispiel "durch Referenz aufgerufen", während der andere durch Variable zugegriffen wird? Warum wird localVariable "nach Wert verwendet?"

Eine Möglichkeit, dies zu verstehen, ist die folgende:

  1. , wenn Sie eine lokale Variable in einem Block in der Methode definiert verwenden, was passiert ist, dass der Inhalt der Variablen in einem gewissen Block kopiert wird privater Speicher, so dass er verfügbar ist, wenn der Block ausgeführt wird (nachdem die Methode beendet wurde); In diesem Sinne sprechen wir vielleicht von "nach Wert" (wie in: der Wert wird kopiert); syntaktisch weiß der Compiler nicht, was der Inhalt von localVariable betrifft, also werden seine Werte als solche behandelt;

  2. Beim direkten Zugriff auf instanceVariable in einem in einer Methode einer Klasse definierten Block weiß der Compiler, dass wir auf dasselbe Objekt zugreifen, das die Methode ausführt, und dass nichts kopiert werden muss, da das Objekt länger ist Lebensdauer als die Methode, in der der Block gefunden wird; aber wir müssen sicherstellen, dass das Objekt immer noch da ist, wenn der Block ausgeführt wird, also erhalten wir einen starken Hinweis darauf.

nun in Bezug auf die Verwendung von „by reference“: im ersten Fall, erhalten Sie eine Kopie des Verweises auf das Klassenmitglied: wenn Sie seinen Wert ändern könnten (aber man kann nicht, weil der Compiler verbietet es), Sie haben gerade eine private Blockkopie geändert, so dass das ursprüngliche Objekt nicht betroffen ist.

Im zweiten Fall können Sie den Wert von instanceVariable ändern (wie in: es war nil und Sie ordnen ein Objekt durch verwiesen) und dies wird Auswirkungen auf das Objekt, das die Methode ausgeführt wurde der Block definiert wurde.

Was bedeutet das Dokument, wenn "ein starker Hinweis auf sich selbst gemacht wird"? Auf welches "Selbst" bezieht es sich?

self ist das Objekt, das gerade die Methode ausführt, in der der Block gefunden wird. dass eine starke Referenz gemacht wird, bedeutet nur (im ARC-Sprachgebrauch), dass die Retain-Zahl des Objekts inkrementiert wird (um sicherzustellen, dass eine andere Entität nicht dazu führen kann, dass sie freigegeben wird, indem sie freigegeben wird).

Wenn ich den __block-Speichertyp im zweiten Beispiel zu localVariable hinzufüge, kann ich falsch davon ausgehen, dass der Block über die Variable schließt, so dass sie im Heap bleibt, bis der Block freigegeben wird? Welche anderen Dinge passieren?

Mit __block wird die Variable immer "per Referenz" aufgerufen, so dass Sie sie ändern können.

Dies ist, wie sie behandelt werden:

__block Variablen leben in Speicher, der zwischen dem lexikalischen Gültigkeitsbereich der Variablen und alle Blöcke und Blockkopien deklariert oder erstellt innerhalb der Variablenlexikalischen Gültigkeitsbereich gemeinsam genutzt wird. Somit wird der Speicher die Zerstörung des Stapelrahmens überleben, wenn irgendwelche Kopien der Blöcke, die innerhalb des Rahmens deklariert sind, über das Ende des Rahmens hinaus bestehen (zum Beispiel, indem sie irgendwo für die spätere Ausführung in eine Warteschlange eingereiht werden). Mehrere Blöcke in einem gegebenen lexikalischen Bereich können gleichzeitig eine gemeinsam genutzte Variable verwenden.

Als Optimierung beginnt der Blockspeicher auf dem Stack - genau wie Blöcke selbst. Wenn der Block mit Block_copy kopiert wird (oder in Objective-C, wenn der Block eine Kopie sendet), werden die Variablen in den Heap kopiert. Daher kann sich die Adresse einer __block-Variablen im Laufe der Zeit ändern.