tipo tiempo parametros objetos objeto instanciar hilos forma ejecucion dinamicos dinamicamente dinamica crear clase arreglos objective-c cocoa properties objective-c-runtime

objective-c - tiempo - parametros dinamicos c#



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

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



Si NSKeyValueCoding un vistazo al protocolo NSKeyValueCoding , documentado here , 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).


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 codificación 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 codificación genérica @ type de id .

Aquí hay un primer borrador de un programa que agrega dinámicamente una propiedad llamada name a una clase que ya tiene una variable de instancia llamada _privateName :

#include <objc/runtime.h> #import <Foundation/Foundation.h> @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.