Is there a way to create a Singleton pattern with objective-c, which would enable the client code to get a shared instance of any of it's subclasses?
I tried:
@interface Base : NSObject {}
+(id)instance;
@end
@implementation Base
static id _instance;
+(id)instance {
if (!_instance) {
_instance = [[self alloc] init];
}
return _instance;
}
@end
But calling any subclass's [AmazingThing instance]
only returns the first instance created through this mechanism, no matter what type the _instance
is. Any clean workarounds?
Edit
I realized (while replying to a deleted answer) that I can do what I was looking for by changing the implementation to be:
static NSMutableDictionary *_instances;
+(id)instance {
if (!_instances) {
_instances = [[NSMutableDictionary alloc] init];
}
id instance = [_instances objectForKey:self];
if (!instance) {
instance = [[self alloc] init];
[_instances setObject:instance forKey:self];
}
return instance;
}
It now works as expected. Still, I'm interested to know if there's a better way to do this.
I would do it like this:
+(id) instance
{
static id theInstance = nil;
if (theInstance == nil)
{
theInstance = [[self alloc] init];
}
return theInstance;
}
Of course you'd need that method in every subclass of your base class in order to get a different static variable for each class. But you would create a #define
in the base class header:
#define CREATE_INSTANCE \
+(id) instance \
{ \
static id theInstance = nil; \
if (theInstance == nil) \
{ \
theInstance = [[self alloc] init]; \
} \
return theInstance; \
}
and then each impementation just has the define in it:
@implementation SubClass
CREATE_INSTANCE
// other stuff
@end
If using Objective-C++ is ok. What you can do is have a meta-programmed C++ class that manages the lifetime of a singleton object.
This way you can use the Singleton pattern and access the singleton using
Derived* d = Singleton<Derived>::get()
.
For further reference you can look at http://src.chromium.org/viewvc/chrome/trunk/src/base/singleton_objc.h this is how chrome manages to do it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With