Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-c singleton baseclass

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.

like image 343
sharvey Avatar asked Feb 26 '23 15:02

sharvey


2 Answers

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
like image 167
JeremyP Avatar answered Mar 11 '23 07:03

JeremyP


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.

like image 21
shreyasva Avatar answered Mar 11 '23 07:03

shreyasva