2009-07-23 12 views
90

È possibile creare un'istanza di una classe per nome? Qualcosa di simile:Creare istanza di classe obiettivo-c per nome?

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

Non so se questo è possibile in Objective-C, ma sembra che sarebbe stato,

risposta

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

Questo non causerà eventuali perdite? – AntiMoron

38

NSClassFromString() corre il rischio di errori di digitazione del nome della classe o comunque utilizzando un classe che non esiste. Non lo scoprirai fino al runtime se fai questo errore. Invece, se si utilizza il tipo di obiettivo-c incorporato di Class per creare una variabile, il compilatore verificherà che la classe esista.

Per esempio, nella vostra .h:

@property Class NameOfClass; 

e poi nel vostro .m:

id object = [[NameOfClass alloc] init]; 

Se sbagliato a digitare il nome della classe o se non esiste, si otterrà un errore al momento della compilazione. Inoltre penso che questo sia un codice più pulito.

+1

chris puoi votarlo? –

+0

ecco, amico. Non è del tutto sicuro che sia la risposta migliore, poiché richiede due righe ed è meno dinamica, ma è in aumento uguale a –

+0

Suppongo che si possa dire che è meno dinamico perché ho usato un simbolo invece di una stringa. Tuttavia, se si conosce la classe che si desidera quando si scrive il codice, è preferibile utilizzare il simbolo per evitare possibili errori di battitura. –

8

Se si lavora con Objective-C, senza il sistema NeXTstep (OS X, iOS, GNUstep ecc) o semplicemente pensi che questo metodo è più pulita, allora si potrebbe utilizzare il Objective-C language runtime library's API. Sotto 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 ]; 

Sotto l'Objective-C (1.0 o versione senza nome) che si utilizzano le seguenti:

#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 ]; 

Non ho ancora testato la versione 1.0, però ho usato la funzione 2.0 nel codice che è ora in produzione. Personalmente ritengo che l'utilizzo della funzione 2.0 sia più pulito se disponibile rispetto alla funzione NS in quanto occupa meno spazio: the length of the name in bytes + 1 (null terminator) per l'API 2.0 rispetto a the sum of two pointers (isa, cstring), uno size_t length (cstring_length) e lo length of the string in bytes + 1 per l'API NeXTSTEP.

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

@implementation Magic 

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

@end 

Poi usarlo:

Car *car = [Magic createInstanceOfClass:[Car class]]; 
[car engineTurnOn]; 
Problemi correlati