Можно ли создать экземпляр класса по имени? Что-то вроде:
NSString* className = @"Car";
id* p = [Magic createClassByName:className];
[p turnOnEngine];
Я не знаю, возможно ли это в objective-c, но похоже, что это было бы,
Ответы:
id object = [[NSClassFromString(@"NameofClass") alloc] init];
NSClassFromString()
рискует ошибиться при вводе имени класса или иным образом использовать несуществующий класс. Вы не узнаете до времени выполнения, если сделаете эту ошибку. Вместо этого, если вы используете встроенный тип objective-c Class
для создания переменной, компилятор проверит, существует ли класс.
Например, в вашем .h
:
@property Class NameOfClass;
а затем в вашем .m
:
id object = [[NameOfClass alloc] init];
Если вы неправильно набрали имя класса или он не существует, вы получите ошибку во время компиляции. Также я думаю, что это более чистый код.
Если вы работаете с Objective-C без системы NeXTstep
( OS X
, iOS
и GNUstep
т. Д.) Или просто думаете, что этот метод чище, то вы можете использовать API библиотеки времени выполнения языка Objective-C . Под 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.