¿Cómo puedo agregar propiedades a un objeto en tiempo de ejecución?

¿Es posible agregar propiedades a un objeto Objective C en tiempo de ejecución?

    Es posible agregar propiedades formales a una clase a través de class_addProperty() :

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

    Los primeros dos parámetros son autoexplicativos. El tercer parámetro es una matriz de atributos de propiedad, y cada atributo de propiedad es un par nombre-valor que sigue codificaciones de tipo Objective-C para las propiedades declaradas . Tenga en cuenta que la documentación aún menciona la cadena separada por comas para la encoding de los atributos de propiedad. Cada segmento en la cadena separada por comas está representado por una instancia objc_property_attribute_t . Además, objc_property_attribute_t acepta nombres de clase además de la encoding genérica @ type de id .

    Aquí hay un primer borrador de un progtwig que agrega dinámicamente una propiedad llamada name a una clase que ya tiene una variable de instancia llamada _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]); } } 

    Su salida (recortada):

     Steve Jobs 

    Los métodos getter y setter deberían escribirse con más cuidado, pero esto debería ser suficiente como un ejemplo de cómo agregar dinámicamente una propiedad formal en tiempo de ejecución.

    Si NSKeyValueCoding un vistazo al protocolo NSKeyValueCoding , documentado aquí , puedes ver que hay un mensaje llamado:

     - (id)valueForUndefinedKey:(NSString *)key 

    Debe anular ese método para proporcionar su resultado personalizado para la propiedad indefinida especificada. Por supuesto, esto supone que su clase utiliza el protocolo correspondiente.

    Este tipo de enfoque se usa comúnmente para proporcionar un comportamiento desconocido a las clases (por ejemplo, un selector que no existe).

    @properties – no (es decir, usando syntax de punto, etc.). Pero puede agregar almacenamiento usando objetos asociados: ¿Cómo uso objc_setAssociatedObject / objc_getAssociatedObject dentro de un objeto? .