2009-07-23 16 views
90

¿Es posible crear una instancia de una clase por nombre? Algo así como:¿Crear instancia de clase objetivo-c por nombre?

NSString* className = @"Car"; 
id* p = [Magic createClassByName:className]; 
[p turnOnEngine]; 

No sé si esto es posible en Objective-C, pero parece que sería,

Respuesta

210
id object = [[NSClassFromString(@"NameofClass") alloc] init]; 
+0

Esto no hará que cualquier fuga? – AntiMoron

38

NSClassFromString() corre el riesgo de escribir mal el nombre de clase o de otra manera usando una clase que no existe No descubrirás hasta el tiempo de ejecución si cometes ese error. En su lugar, si usa el tipo de objetivo-c incorporado de Class para crear una variable, el compilador verificará si existe la clase.

Por ejemplo, en su .h:

@property Class NameOfClass; 

y luego en su .m:

id object = [[NameOfClass alloc] init]; 

Si se equivoca el nombre de clase o si no existe, obtendrá una error en tiempo de compilación. También creo que este es un código más limpio.

+1

Chris, ¿puedes votarlo entonces? –

+0

ahí lo tienes, amigo. No estoy del todo seguro de que sea la mejor respuesta, ya que requiere dos líneas y es menos dinámico, pero votó por encima del mismo –

+0

Supongo que podría decir que es menos dinámico porque utilicé un símbolo en lugar de una cadena. Sin embargo, si conoce la clase que desea cuando está escribiendo el código, entonces es preferible utilizar el símbolo para evitar posibles errores tipográficos. –

8

Si está trabajando con Objective-C sin el (, iOS, etc GNUstepOS X) Sistema NeXTstep o simplemente piensa que este método es más limpio, entonces se podría utilizar el Objective-C language runtime library's API. Bajo Objective-C 2.0:

#import <objc/runtime.h> 
//Declaration in the above named file 
id objc_getClass(const char* name); 
//Usage 
id c = objc_getClass("Object"); 
[ [ c alloc ] free ]; 

Bajo el Objective-C (1.0 o versión sin nombre) que utilizaría el siguiente:

#import <objc/objc-api.h> 
//Declaration within the above named file 
Class objc_get_class(const char* name); 
//Usage 
Class cls = objc_get_class("Test"); 
id obj = class_create_instance(cls); 
[ obj free ]; 

no he probado la versión 1.0, sin embargo, he utilizado la función 2.0 en el código que ahora está en producción. Personalmente creo que la utilización de la función 2.0 es más limpia si está disponible que la función NS ya que consume menos espacio: the length of the name in bytes + 1 (null terminator) para la API 2.0 frente a the sum of two pointers (isa, cstring), una size_t length (cstring_length) y la length of the string in bytes + 1 para la API NeXTSTEP.

2
@interface Magic : NSObject 
+ (id)createInstanceOfClass:(Class)classe; 
@end 

@implementation Magic 

+ (id)createInstanceOfClass:(Class)classe 
{ 
    return [[classe alloc] init]; 
} 

@end 

Luego de usarlo:

Car *car = [Magic createInstanceOfClass:[Car class]]; 
[car engineTurnOn]; 
Cuestiones relacionadas