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

StackOverflow https://stackoverflow.com/questions/315591

Вопрос

Я работаю над фабрикой объектов, чтобы отслеживать небольшую коллекцию объектов. Объекты могут быть разных типов, но все они будут реагировать на 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)];
}
Это было полезно?

Решение

Вы можете преобразовать строку в класс, используя функцию: 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;
}

Другие советы

У меня есть правильный учебник по этому вопросу, пожалуйста, проверьте https://appengineer.in/ 2014/03/13 / отправить-имя-класса-как-аргумент-в-КСН /

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

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

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

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

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

- (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]];
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top