Как передать имя класса в качестве аргумента для объекта factory в cocoa?

Я работаю над объектом factory, чтобы отслеживать небольшую коллекцию объектов. Объекты могут быть разных типов, но все они будут реагировать на createInstance и reset. Объекты не могут быть получены из общего базового класса, потому что некоторые из них должны будут выводиться из встроенных классов cocoa, таких как NSView и NSWindowController.

Я хотел бы иметь возможность создавать экземпляры любого подходящего объекта, просто передав нужное имя класса моему factory следующим образом:

myClass * variable = [factory makeObjectOfClass:myClass];

Метод makeObjectOfClass: будет выглядеть примерно так:

- (id)makeObjectOfClass:(CLASSNAME)className
{
    assert([className instancesRespondToSelector:@selector(reset)]);
    id newInstance = [className createInstance];
    [managedObjects addObject:newInstance];
    return newInstance;
}

Есть ли способ передать имя класса методу, как это было сделано с аргументом (CLASSNAME)className в makeObjectOfClass: выше?

Для полноты, вот почему я хочу управлять всеми объектами. Я хочу, чтобы reset полный набор объектов в один кадр, вызывая [factory reset];.

- (void)reset
{
    [managedObjects makeObjectsPerformSelector:@selector(reset)];
}

Ответы

Ответ 1

Вы можете преобразовать строку в класс с помощью функции: NSClassFromString

Class classFromString = NSClassFromString(@"MyClass");

В вашем случае, однако, вам лучше использовать объекты класса напрямую.

MyClass * variable = [factory makeObjectOfClass:[MyClass class]];

- (id)makeObjectOfClass:(Class)aClass
{
    assert([aClass instancesRespondToSelector:@selector(reset)]);
    id newInstance = [aClass createInstance];
    [managedObjects addObject:newInstance];
    return newInstance;
}

Ответ 3

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

id string = [[NSClassFromString(@"NSString") alloc] initWithString:@"Hello!"];
NSLog( @"%@", string );

Еще один совет, я бы не использовал номенклатурный "управляемый объект", так как большинство других программистов Cocoa будут читать это как NSManagedObject, из Core Data. Вам также может быть проще использовать глобальную NSNotification (чтобы все ваши reset -able объекты подписывались) вместо управления коллекцией различных типов объектов, но вы более информированы о принятии этого решения, чем я.

Ответ 4

Бит ответа, отсутствующий в других ответах, заключается в том, что вы можете определить @protocol, содержащий ваши методы +createInstance и +reset.

Ответ 5

Похоже, вы хотите что-то вроде:

- (id)makeObjectOfClassNamed:(NSString *)className
{
    Class klass = NSClassFromString(className);
    assert([klass instancesRespondToSelector:@selector(reset)]);
    id newInstance = [klass createInstance];
    [managedObjects addObject:newInstance];
    return newInstance;
}

Это предполагает метод класса с именем +createInstance. Или вы можете просто использовать [[klass alloc] init].

Чтобы вызвать его:

MyClass *variable = [factory makeObjectOfClassNamed:@"MyClass"];

В зависимости от того, что вы пытаетесь сделать, может быть лучше передать объекты класса, чем строки, например:

MyClass *variable = [factory makeObjectOfClass:[MyClass class]];