What I have:
I have multiple singletons in my project and they share some scope, fields and functionality. So I decided to structurize them and create a parent class called BaseSingleton. As a singleton, it has +(instancetype) sharedInstance
, so will all of its subclasses. Right now I have a BaseSingleton
class and three subclasses:
+(instancetype) sharedInstance
in BaseSingleton has a common implementation:
+(instancetype) sharedInstance {
static BaseSingleton* _sharedInstance = nil;
static dispatch_once_t once_token;
dispatch_once(&once_token, ^{
_sharedInstance = [[self alloc] init]; // no override for init method
});
return _sharedInstance;
}
What I need:
I need my Singleton subclasses to work properly when sharedInstance
is invoked on them. Meaning, PublicApi
returns an instance of PublicApi
, UserService
returns UserService
and OrderStorage
returns OrderStorage
instance, with no need to implement sharedInstance.
What the problem is::
So I thought that utilizing instancetype
in +(instancetype) sharedInstance
would do the work, because using instancetype
makes class method return related return type (read in NSHipster article). So if called on PublicApi or UserService, sharedInstance
would return related type, which is PublicApi or UserService respectively (again, without implementing sharedInstance
in neither of them).
This worked good with only one subclass (PublicApi
). But when added other two subclasses, Calling sharedInstance
on some of them would not exactly result in correct return type. So for example, [PublicApi sharedInstance]
would return an instance of PublicApi
, But [UserService sharedInstance]
would also return an instance of PublicApi
, same thing for OrderStorage
.
I think the problem lays in static _sharedInstance
in [BaseSingleton sharedInstance]
implementation. [PublicApi sharedInstance]
is called first during application runtime, so dispatch_once
method instantiates _sharedInstance
and gives it a PublicApi
type. Code block inside dispatch_once
is never executed again, that is why that static variable never changes its type and is returned as PublicApi
in [UserService sharedInstance]
and [OrderStorage sharedInstance]
.
Any elegant way to do what I am asking about? (Besides implementing sharedInstance
for each subclass of course, that defeats the whole purpose of inheriting from BaseSingleton).
A common base class for singletons is a contradiction in itself.
What should be obvious is that with your sharedSingleton implementation, there is only one dispatch_once_t token. So the code inside dispatch_once_t will only be executed once in your application. There is also only one static variable for _sharedInstance, so it cannot possibly return two different sharedInstance values.
Don't do this.