开发者

Does NSClassFromString affect performance?

开发者 https://www.devze.com 2023-01-01 07:39 出处:网络
I want to create a controller that depends on the class of a given instance of a model -(BaseController *)getControllerForModel:(Model *)model

I want to create a controller that depends on the class of a given instance of a model

 -(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;
    }

I want to find a more flexible solution to this and thought of having a dictionary, which maps Model-Classes to Controller-Classes and then NSClassFromString could give me the right instance.

My question is this: Is NSClassFromString using much of my applications performance if i use it several times (say, 100 times at once)? Or would it be about 开发者_开发知识库as fast as the above approach?


Generally, use of isMemberOfClass: in such a fashion indicates an architectural issue.

In this case, why can't the various Model classes simply implement a +controllerClass method?

I can understand Nikolai's desire to maintain the layering of Controller on top of Model without the Model having knowledge of the Controller. However, my experience is that any control layer that has such type specific knowledge of the Model quickly destroys that isolation anyway; the model layer quickly evolves behaviors that are controller specific.

Thus, the added complexity injected by attempting to maintain that separation just isn't worth it.


A Class is an id, and as such can be added to an NSDictionary. You should try the following:

mModelToControllerMap = [[NSDictionary alloc] initWithObjectsAndKeys:
   [ConcreteController1 class] , [ModelClass1 class] ,
   [ConcreteController2 class] , [ModelClass2 class] ,
   ...
   nil];

Then later:

controllerClass = [mModelToControllerMap objectForKey:[modelInstance class]];
if ( controllerClass ) ...
else ...

If you make it a mutable dictionary, you can then have controllers register for the models they want instead of forcing the base class to be aware of all derived classes.

And a direct answer. At worst, NSClassFromString may need to iterate through all classes to find a match. It could also be a dictionary lookup, but the implementation is not documented and should not be relied on. While doing it a few hundred times probably isn't too bad, there are better ways.


If you're really concerned about performance, you could cache the results of the NSClassFromString and put them in a dictionary.

On the other hand, that's probably pretty much what NSClassFromString really does (a map lookup). So I'd say it's much faster that the 100x if approach.

But anyway: Just give it a try, as with all performance issues.


NSStringFromClass shouldn't be much more expensive. In fact, in your case you could use it much more effectively. I don't know your exact class naming convention, but using a methof like this could be much smaller and faster:

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);

as bbum suggested you could also make this a method on a common parent of the model classes.

0

精彩评论

暂无评论...
验证码 换一张
取 消