Создать экземпляр класса objective-c по имени?

Можно ли создать экземпляр класса по имени? Что-то вроде:

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

Я не знаю, возможно ли это в objective-c, но похоже, что это будет,

Ответ 1

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

Ответ 2

NSClassFromString() запускает риск ошибочного использования имени класса или иным образом с использованием класса, который не существует. Если вы сделаете эту ошибку, вы не узнаете ее до выполнения. Вместо этого, если вы используете встроенный objective-c тип Class для создания переменной, тогда компилятор проверяет, существует ли класс.

Например, в .h:

@property Class NameOfClass;

а затем в .m:

id object = [[NameOfClass alloc] init];

Если вы ошибочно указали имя класса или если оно не существует, во время компиляции вы получите сообщение об ошибке. Также я думаю, что это более чистый код.

Ответ 3

Если вы работаете с Objective-C без NeXTstep (OS X, iOS, GNUstep и т.д.), или вы просто думаете, что этот метод более чист, вы можете использовать Objective-C API библиотеки языка исполнения. В разделе 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 ];

В Objective-C (1.0 или неназванная версия) вы должны использовать следующее:

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

Я не тестировал версию 1.0, однако я использовал функцию 2.0 в коде, который сейчас находится в производстве. Я лично считаю, что использование функции 2.0 является более чистым, если доступно, чем функция NS, поскольку оно потребляет меньше места: the length of the name in bytes + 1 ( null terminator ) для API 2.0 по сравнению с the sum of two pointers (isa, cstring), a size_t length (cstring_length) и length of the string in bytes + 1 для NeXTstep API.

Ответ 4

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

@implementation Magic

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

@end

Затем, чтобы использовать его:

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