Ich habe gelesen, dass @synthesize
erstellt automatisch die entsprechenden Instanzvariablen für @property
und die Ivars sind standardmäßig @protected
. Aber was, wenn ich eine Klassenerweiterung verwenden (wie unten), um anzuzeigen, dass die @property
Methoden sind privat sein?
Ist der entsprechende ivar dann @private
? Oder sollte ich es explizit als @private
so deklarieren?
@private
Instanzvariablen sind eine Nur-Kompilierzeit-Funktion. Angesichts der Tatsache, dass die Hintergrundinformationen für @property
bereits ausgeblendet sind, macht @private
nichts. Im Wesentlichen ist es bereits @private
.
Ich beantworte Kevins Antwort:
Wenn Sie eine Klasse deklarieren, z. B .:
%Vor%Der Compiler 1 entscheidet über das Layout einer Instanzvariablen für diese Klasse. Dieses Layout bestimmt Offsets von Instanzvariablen in Bezug auf die Adresse von Instanzen dieser Klasse. Ein mögliches Layout wäre:
%Vor%Wenn eine Instanz-Variable wird in Code verwiesen wird - entweder in der Implementierung der Klasse oder in einem anderen Teil der Codebasis, ersetzt die Compiler, die Referenz mit dem den Instanzvariablen entsprechenden Offset in Bezug auf die Adresse des entsprechenden Instanz.
Zum Beispiel in der Implementierung von SomeClass,
%Vor%oder
%Vor%wird wie folgt übersetzt:
%Vor%Auch außerhalb der Klasse
%Vor%wird wie folgt übersetzt:
%Vor%Der Compiler lässt dies jedoch nur entsprechend der Sichtbarkeit der Instanzvariablen zu:
Wenn eine Instanzvariable in einer Klassenerweiterung deklariert ist, z. B.
%Vor%Der Compiler fügt es dem Layout der Instanzvariablen hinzu:
%Vor%und jeder Verweis auf diese Instanzvariable wird durch ihren entsprechenden Offset in Bezug auf die Instanz ersetzt. Jedoch nur, da diese Instanzvariable der Implementierungsdatei bekannt ist, wo die Klassenerweiterung erklärt wurde, wird der Compiler erlaubt keine anderen Dateien, die es zu verweisen. Eine beliebige Quelldatei kann nur auf Instanzvariablen verweisen, die sie kennt (unter Berücksichtigung der Sichtbarkeitsregeln). Wenn Instanzvariablen werden in einer Header-Datei deklariert, die von einer Quelldatei importiert wird, dann ist die Quelldatei (oder, genauer gesagt, der Compiler während diese Einheit zu übersetzen) ist sich bewusst von ihnen.
Auf der anderen Seite ist eine Erweiterungsvariable nur durch die Quelldatei bekannt, in der sie deklariert wurde. Wir können also sagen, dass Instanzvariablen, die in Klassenerweiterungen deklariert sind, vor anderen Dateien verborgen sind. Die gleiche Argumentation gilt auch für die Unterstützung von Instanzvariablen von Eigenschaften, die in Klassenerweiterungen deklariert sind. Es ist ähnlich wie @private
, aber restriktiver.
Beachten Sie jedoch, dass zur Laufzeit Sichtbarkeitsregeln nicht erzwungen werden. Verwenden der Key-Wert Codierung, eine beliebige Quelldatei manchmal kann (die Regeln beschrieben, hier ) greifen Sie auf eine Instanzvariable zu:
%Vor%enthält eine Instanzvariable, die in einer Erweiterung deklariert ist:
%Vor%Unabhängig von KVC kann der Zugriff auf Instanzvariablen über die Objective-C-Laufzeit-API erfolgen:
%Vor%Beachten Sie, dass eine Klasse mehr als eine Klassenerweiterung haben kann. Eine Klassenerweiterung kann jedoch keine Instanzvariable mit demselben Namen wie eine andere Instanzvariable deklarieren, einschließlich Instanzvariablen, die in anderen Klassenerweiterungen deklariert sind. Da der Compiler Symbole wie folgt ausgibt:
%Vor%für jede Instanz Variable, mit unterschiedlichen Erweiterungen Instanzvariablen mit dem gleichen Namen erklären nicht einen Compiler-Fehler ergeben, weil eine bestimmte Quelldatei nicht bewusst eine anderen Quelldatei ist, aber es hat einen Linkerfehler ergeben.
1 Dieses Layout kann durch die Objective-C-Laufzeit geändert werden. In der Tat sind Offsets durch den Compiler und gespeichert als Variablen berechnet, und die Laufzeit kann sie nach Bedarf ändern.
PS: Nicht alles in dieser Antwort gilt für alle Compiler / Runtime-Versionen. Ich habe nur Objective-C 2.0 mit nicht-fragilen ABI und neueren Versionen von Clang / LLVM betrachtet.
Tags und Links objective-c properties private instance-variables