Как я могу передать имя класса в качестве аргумента фабрике объектов в какао? - PullRequest
15 голосов
/ 25 ноября 2008

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

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

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: выше?

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

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

Ответы [ 5 ]

22 голосов
/ 25 ноября 2008

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

Class classFromString = NSClassFromString(@"MyClass");

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

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

- (id)makeObjectOfClass:(Class)aClass
{
    assert([aClass instancesRespondToSelector:@selector(reset)]);
    id newInstance = [aClass createInstance];
    [managedObjects addObject:newInstance];
    return newInstance;
}
5 голосов
/ 28 апреля 2015

У меня есть правильный учебник по этому вопросу, пожалуйста, проверьте https://appengineer.in/2014/03/13/send-class-name-as-a-argument-in-ios/

3 голосов
/ 25 ноября 2008

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

3 голосов
/ 25 ноября 2008

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

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

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

2 голосов
/ 25 ноября 2008

Звучит так, будто вы хотите что-то вроде:

- (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]];
...