Come posso aggiungere proprietà a un object in fase di runtime?

È ansible aggiungere proprietà a un object Objective C in fase di runtime?

È ansible aggiungere proprietà formali a una class tramite class_addProperty() :

 BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount) 

I primi due parametri sono auto-esplicativi. Il terzo parametro è un array di attributi di proprietà, e ogni attributo di proprietà è una coppia nome-valore che segue le codifiche di tipo Objective-C per le proprietà dichiarate . Si noti che la documentazione menziona ancora la stringa separata da virgola per la codifica degli attributi di proprietà. Ogni segmento nella stringa separata da virgola è rappresentato da un’istanza objc_property_attribute_t . Inoltre, objc_property_attribute_t accetta nomi di classi oltre alla codifica generica di tipo @ di id .

Ecco una prima bozza di un programma che aggiunge dynamicmente una proprietà chiamata name a una class che ha già una variabile di istanza chiamata _privateName :

 #include  #import  @interface SomeClass : NSObject { NSString *_privateName; } @end @implementation SomeClass - (id)init { self = [super init]; if (self) _privateName = @"Steve"; return self; } @end NSString *nameGetter(id self, SEL _cmd) { Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName"); return object_getIvar(self, ivar); } void nameSetter(id self, SEL _cmd, NSString *newName) { Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName"); id oldName = object_getIvar(self, ivar); if (oldName != newName) object_setIvar(self, ivar, [newName copy]); } int main(void) { @autoreleasepool { objc_property_attribute_t type = { "T", "@\"NSString\"" }; objc_property_attribute_t ownership = { "C", "" }; // C = copy objc_property_attribute_t backingivar = { "V", "_privateName" }; objc_property_attribute_t attrs[] = { type, ownership, backingivar }; class_addProperty([SomeClass class], "name", attrs, 3); class_addMethod([SomeClass class], @selector(name), (IMP)nameGetter, "@@:"); class_addMethod([SomeClass class], @selector(setName:), (IMP)nameSetter, "v@:@"); id o = [SomeClass new]; NSLog(@"%@", [o name]); [o setName:@"Jobs"]; NSLog(@"%@", [o name]); } } 

La sua uscita (tagliata):

 Steve Jobs 

I metodi getter e setter dovrebbero essere scritti con più attenzione, ma questo dovrebbe essere sufficiente come esempio di come aggiungere dynamicmente una proprietà formale in fase di runtime.

Se dai un’occhiata al protocollo NSKeyValueCoding , documentato qui , puoi vedere che c’è un messaggio chiamato:

 - (id)valueForUndefinedKey:(NSString *)key 

È necessario sovrascrivere tale metodo per fornire il risultato personalizzato per la proprietà non definita specificata. Ovviamente questo presuppone che la tua class utilizzi il protocollo corrispondente.

Questo tipo di approccio è comunemente utilizzato per fornire un comportamento sconosciuto alle classi (ad esempio un selettore che non esiste).

@properties – no (cioè utilizzando la syntax del punto ecc.). Ma puoi aggiungere memoria usando gli oggetti associati: come posso usare objc_setAssociatedObject / objc_getAssociatedObject all’interno di un object? .