我想创建一个依赖于模型的给定实例的类的控制器
-(BaseController *)getControllerForModel:(Model *)model
{
BaseController *controller = nil;
Class controllerClass = [BaseController class]; //the default value
//find the right controller
if ([model isMemberOfClass:[ModelClass1 class]])
controllerClass = [ConcreteController1 class];
else if ([model isMemberOfClass:[ModelClass2 class]])
controllerClass = [ConcreteController2 class];
else if ([model isMemberOfClass:[ModelClass3 class]])
controllerClass = [ConcreteController3 class];
...
else if ([model isMemberOfClass:[ModelClassX class]])
controllerClass = [ConcreteControllerX class];
else
Trace(TRACELEVEL_WARNING, @"Unrecognized model type: %@", NSStringFromClass([model class]));
//Now instantiate it with the model
controller = [[[controllerClass alloc] initWithModel:model] autorelease];
return slotController;
}
我想找到一个更灵活的解决方案,并想到有一个字典,它将Model-Classes映射到Controller-Classes,然后NSClassFromString
可以给我正确的实例。
我的问题是:如果我多次使用它(例如,一次100次),NSClassFromString
是否会使用我的应用程序的大部分性能?或者它会与上述方法一样快?
答案 0 :(得分:5)
通常,以这种方式使用isMemberOfClass:
表示存在架构问题。
在这种情况下,为什么各种Model
类只能实现+controllerClass
方法?
我可以理解Nikolai希望在没有模型知道控制器的情况下维持控制器在模型之上的分层。但是,我的经验是,任何具有模型特定类型知识的控制层都会迅速破坏隔离;模型层可以快速发展控制器特定的行为。
因此,试图维持这种分离所增加的复杂性并不值得。
答案 1 :(得分:3)
Class是一个id,因此可以添加到NSDictionary中。您应该尝试以下方法:
mModelToControllerMap = [[NSDictionary alloc] initWithObjectsAndKeys:
[ConcreteController1 class] , [ModelClass1 class] ,
[ConcreteController2 class] , [ModelClass2 class] ,
...
nil];
然后:
controllerClass = [mModelToControllerMap objectForKey:[modelInstance class]];
if ( controllerClass ) ...
else ...
如果你把它变成一个可变字典,你就可以让控制器注册他们想要的模型,而不是强迫基类知道所有派生类。
直接回答。在最坏的情况下,NSClassFromString可能需要遍历所有类以查找匹配项。它也可以是字典查找,但实现没有记录,不应该依赖。虽然这样做几百次可能并不太糟糕,但有更好的方法。
答案 2 :(得分:2)
如果您真的关心性能,可以缓存NSClassFromString
的结果并将它们放在字典中。
另一方面,这可能是NSClassFromString
真正做的事情(地图查找)。所以我会说,100x if的速度要快得多。
但无论如何:只要试一试,就像所有性能问题一样。
答案 3 :(得分:2)
NSStringFromClass
不应该贵得多。事实上,在您的情况下,您可以更有效地使用它。我不知道你确切的类命名约定,但使用像这样的方法可能会更小更快:
NSString * modelClassName = NSStringFromClass([model class]);
// get the suffix of class name
// for example, '3' in 'ModelClass3'
NSString * suffix = [modelClassName substringFromIndex:10];
// create the controller name
NSString * controllerName = [NSString stringWithFormat:@"ConcreteController%@", suffix];
/* do something if name is not valid */
controllerClass = NSClassFromString(controllerName);
正如bbum建议你也可以在模型类的公共父类上创建一个方法。