Reputation: 119214
I am working on an object factory to keep track of a small collection of objects. The objects can be of different types, but they will all respond to createInstance
and reset
. The objects can not be derived from a common base class because some of them will have to derive from built-in cocoa classes like NSView
and NSWindowController
.
I would like to be able to create instances of any suitable object by simply passing the desired classname to my factory as follows:
myClass * variable = [factory makeObjectOfClass:myClass];
The makeObjectOfClass:
method would look something like this:
- (id)makeObjectOfClass:(CLASSNAME)className
{
assert([className instancesRespondToSelector:@selector(reset)]);
id newInstance = [className createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
Is there a way to pass a class name to a method, as I have done with the (CLASSNAME)className
argument to makeObjectOfClass:
above?
For the sake of completeness, here is why I want to manage all of the objects. I want to be able to reset the complete set of objects in one shot, by calling [factory reset];
.
- (void)reset
{
[managedObjects makeObjectsPerformSelector:@selector(reset)];
}
Upvotes: 17
Views: 10431
Reputation: 1949
I have right a better tutorial on that , please checkout https://appengineer.in/2014/03/13/send-class-name-as-a-argument-in-ios/
Upvotes: 5
Reputation: 14968
You can convert a string to a class using the function: NSClassFromString
Class classFromString = NSClassFromString(@"MyClass");
In your case though, you'd be better off using the Class objects directly.
MyClass * variable = [factory makeObjectOfClass:[MyClass class]];
- (id)makeObjectOfClass:(Class)aClass
{
assert([aClass instancesRespondToSelector:@selector(reset)]);
id newInstance = [aClass createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
Upvotes: 23
Reputation:
The bit of the answer missing from the other answers is that you could define a @protocol
containing your +createInstance
and +reset
methods.
Upvotes: 3
Reputation: 2030
It sounds like you want something like:
- (id)makeObjectOfClassNamed:(NSString *)className
{
Class klass = NSClassFromString(className);
assert([klass instancesRespondToSelector:@selector(reset)]);
id newInstance = [klass createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
This would assume a class method named +createInstance
. Or you could just use [[klass alloc] init]
.
To call it:
MyClass *variable = [factory makeObjectOfClassNamed:@"MyClass"];
Depending on what you're trying to do, it might be better to pass around class objects than strings, e.g.:
MyClass *variable = [factory makeObjectOfClass:[MyClass class]];
Upvotes: 2
Reputation: 40513
It's pretty easy to dynamically specify a class, in fact you can just reference it by it's name:
id string = [[NSClassFromString(@"NSString") alloc] initWithString:@"Hello!"];
NSLog( @"%@", string );
One other tip, I would avoid using the nomenclature 'managed object' since most other Cocoa programmers will read that as NSManagedObject, from Core Data. You may also find it easier to use a global NSNotification (that all your reset-able objects subscribe to) instead of managing a collection of different types of objects, but you're more informed to make that decision than I am.
Upvotes: 3