我想创建一个依赖于给定模型实例的类的控制器
-(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;
}
我想找到一个更灵活的解决方案,并想到有一个字典,它将模型类映射到控制器类,然后
NSClassFromString
可以给我正确的实例。
我的问题是:如果我多次使用
NSClassFromString
(例如一次 100 次),它是否会占用我的应用程序的大部分性能?或者它会和上述方法一样快吗?
通常,以这种方式使用
isMemberOfClass:
表明存在架构问题。
既然如此,为什么各个
Model
类不能简单地实现一个+controllerClass
方法呢?
我可以理解尼古拉希望在模型不了解控制器的情况下维持控制器分层的愿望。 然而,我的经验是,任何具有模型的此类特定知识的控制层都会很快破坏这种隔离; 模型层快速演化出特定于控制器的行为。
因此,通过尝试维持这种分离而增加的复杂性是不值得的。
类是一个 id,因此可以添加到 NSDictionary 中。 您应该尝试以下操作:
mModelToControllerMap = [[NSDictionary alloc] initWithObjectsAndKeys:
[ConcreteController1 class] , [ModelClass1 class] ,
[ConcreteController2 class] , [ModelClass2 class] ,
...
nil];
然后:
controllerClass = [mModelToControllerMap objectForKey:[modelInstance class]];
if ( controllerClass ) ...
else ...
如果将其设为可变字典,则可以让控制器注册它们想要的模型,而不是强制基类了解所有派生类。
还有直接的答案。 最坏的情况下,NSClassFromString 可能需要遍历所有类才能找到匹配项。 它也可以是字典查找,但实现没有记录,不应依赖。 虽然做几百次可能还不错,但还有更好的方法。
如果您真的关心性能,您可以缓存
NSClassFromString
的结果并将它们放入字典中。
另一方面,这可能就是
NSClassFromString
真正做的事情(地图查找)。所以我想说它比 100x if 方法快得多。
但无论如何:尝试一下,就像解决所有性能问题一样。
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 建议的那样,您也可以将其作为模型类的公共父级的方法。
请记住,nib/xib 文件将文件的所有者类存储为字符串,因此 nib 实例化需要通过字符串进行查找。这使得苹果公司不太可能使用效率极低的查找。 (他们也不太可能实现高效的查找,将其保持私有,实现单独的低效查找并公开它。)