2008-11-08 4 views
22

Eines der Merkmale der modernen Objective-C-Laufzeit (64 Bit OS X und iPhone OS) ist die Fähigkeit, Eigenschaften dynamisch zu synthetisieren, ohne sie explizit zu deklarieren die Klasse:Was ist der zugrundeliegende Mechanismus für die Synthese von Ivar in der modernen Objective-C-Laufzeit?

@interface MyClass : NSObject { 
// NSString *name; unnecessary on modern runtimes 
} 

@property (retain) NSStrng *name; 

@end 

@implementation MyClass 

@synthesize name; 

@end 

in ziemlich viel mein Code verwende ich benutzerdefinierte Getter-Implementierungen, um die Eigenschaften zu initialisieren:

- (NSString *) name { 
    if (!name) { 
    name = @"Louis"; 
    } 

    return name; 
} 

die oben ist nicht kompatibel mit synthetisierten ivars, da sie eine eine zugreifen muss Ivar das ist nicht deklarieren Ed in der Kopfzeile. Aus verschiedenen Gründen möchte ich einige meiner persönlichen Frameworks aktualisieren, um synthetisierte Ivars zu verwenden, wenn sie auf modernen Laufzeiten basieren. Der obige Code muss modifiziert werden, um mit synthetisierten Ivars zu arbeiten, um dieses Ziel zu erreichen.

Während die Objective C 2.0 Dokumentation besagt, dass die synthetisierten Accessoren auf der modernen Laufzeit den Ivar bei der ersten Verwendung synthetisieren wird. Es gibt nicht an, welcher Low-Level-Mechanismus dafür verwendet wird. Ist es erledigt durch class_getInstanceVariable(), sind die Beschränkungen für class_addIvar() gelockert, ist es eine undokumentierte Funktion in der objektiven C 2.0 Laufzeit? Während ich meinen eigenen Side-Speicher für die Daten implementieren könnte, die meine Eigenschaften unterstützen, würde ich viel lieber den Mechanismus verwenden, den synthetisierte Accessoren verwenden.

+1

ich wirklich beeindruckt sein würde, wenn Sie eine Antwort auf diese – Shawn

Antwort

21

Ich ging gerade und sah mir die Dokumentation noch einmal an, und ich glaube, Sie haben es falsch verstanden. Synthetisierte Ivars werden zur Kompilierzeit und nicht zur Laufzeit erstellt.

Nach den Objective-C 2.0 documentation:

Es gibt Unterschiede im Verhalten, die auf der Laufzeit abhängig (siehe auch „Runtime Differences“):

Für das Legacy-Runtimes, Instanzvariablen müssen bereits deklariert werden im @interface-Block. Wenn eine Instanzvariable mit demselben Namen und demselben kompatiblen Typ wie die Eigenschaft vorhanden ist, wird sie verwendet. Andernfalls wird ein Compilerfehler angezeigt.

Für die modernen Laufzeiten werden Instanzvariablen nach Bedarf synthetisiert. Wenn bereits eine Instanzvariable mit demselben Namen vorhanden ist, wird sie verwendet.

Also alles, was Sie tun müssen, ist die Instanz-Variable deklarieren Sie brauchen, und der gleiche Code wird auf beiden Runtimes arbeiten ...

+2

bekam nach der Lektüre dieses durch Synthesizer-Code des gcc in der Tat, was ist geht weiter. –

+1

Eine der Verbesserungen in den Compilern der Xcode 3.2-Ära (Clang/LLVM und GCC 4.2) besteht darin, dass Sie auf Ivars zugreifen können, die synthetisierte Variablen unterstützen, selbst wenn sie nicht in der Klasse deklariert sind . –

-6

Sie Eigenschaften hinzufügen zu Laufzeit mit dem NSKeyValueCoding Protocol.

[myObject setValue:@"whatever" forKey:@"foo"]; 
+2

Das ist falsch. Sie können Werte mit Schlüsselwertcodierung * setzen *, Sie können jedoch keine Eigenschaften auf diese Weise hinzufügen. – jlehr

+0

Sie können absolut neue Werte mit NSKeyValueCoding hinzufügen, wenn die Klasse dieses Protokoll implementiert. Aber Sie haben Recht, dass dies die falsche Antwort auf diese Frage ist, da Ivars zur Kompilierzeit erstellt werden, nicht mit NSKeyValueCoding. – jazzdev

+1

Lesen Sie die Antwort erneut. Sie können keine * Eigenschaften * über Schlüsselwertcodierung hinzufügen. – jlehr

0

Was Sie suchen Name @synthesized wird, wie:

@synthesize name = _name; 

... 

- (NSString *) name { 
    if (!name) { 
     _name = @"Louis"; 
    } 

    return _name; 
}