Как я могу динамически создать экземпляр класса? - PullRequest
3 голосов
/ 27 мая 2009

Пример:

У меня есть 10 контроллеров представления, которые распределены и инициализированы одинаково:

UIViewController *controller = [[MyViewController alloc] initWithNib];

(обратите внимание, что -initWithNib - это пользовательский метод подкласса UIViewController)

Следующим классом контроллера представления является OtherViewController и т. Д. Я хочу загружать контроллеры представления лениво, только когда они мне нужны. Но для этого мне нужен какой-то «массив», который даст мне соответствующий класс для данного индекса, чтобы я мог его инициализировать.

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

Есть ли способ достичь этого?

РЕДАКТИРОВАТЬ: Я нашел функцию

id class_createInstance(Class cls, size_t extraBytes)

и кажется, что у каждого класса есть свойство "класс". Но я не могу присвоить его переменной экземпляра. Это не работает:

Class cls = [UIImage class];
cls *image = [cls imageNamed:@"avatar.png"];

Первая строка компилируется. Но второй выдает ошибку: «изображение необъявлено».

Ответы [ 5 ]

13 голосов
/ 27 мая 2009

Если вы знаете имена классов во время компиляции, вы можете назначить классы переменным класса. Например:

static Class factory[2];

factory[0] = [MyViewController1 class];
factory[1] = [MyViewController2 class];
...

Тогда вы могли бы иметь (classid будет известной во время компиляции константой, которая будет отображаться в желаемый класс:

-(UIViewController*)createViewController:(int)classid
{
    return [[factory[classid] alloc] init];
}

Предполагая, что метод определен в классе с именем MyFactory, вы можете выполнить:

MyFactory * fac = [[MyFactory alloc] init];
UIViewController * v1 = [fac createViewController: 0]; // typed
id v2 = [fac createViewController: 1]; // untyped

Если у вас нет имени класса времени компиляции, вы можете просто сделать следующее:

#include <objc/objc-runtime.h>

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

Поскольку ваш первоначальный вопрос связан с набором UIViewControllers, нет смысла терять безопасность типов с помощью последнего метода.

6 голосов
/ 27 мая 2009

Вы хотите использовать отражение:

 id controller = class_createInstance(NSClassFromString(@"your class name"), 0/*extra bytes*/);

Objective-C Runtime Reference

1 голос
/ 15 июня 2009

Я писал об этом в прошлом месяце по адресу: http://igotosoft.blogspot.com/2009/05/dynamically-creating-viewscontrollers.html По сути, он включает новый класс, который я называю ClassConstructor, который принимает имя класса, имя метода init и разделенные запятыми аргументы. Когда вам нужно создать экземпляр этого класса, просто используйте [myClassConstructor create];

0 голосов
/ 27 мая 2009

Objective C Reference также будет хорошим местом для поиска звонков. Попробуйте выполнить поиск по Objective-C 2.0, поскольку я не могу добавить ссылки

0 голосов
/ 27 мая 2009

То, что вы хотите, это отражение. Хотя понятия о цели-c нет, но этот термин может помочь вам Google лучше ответить на ваш вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...