In general your constructor shouldn't enforce singleness. Your instance
method should (which it does). The reason for this is that you may want a singleton of the object as well as the ability to create other instances of the object.
As for the code you provided your init
is not thread safe. It would be possible for two separate threads to assign to gInstance
. The thread that sets it first would leak memory. And other subtle bugs could result. For example if the singleton was some sort of shared datastore the thread that won the race would effectively have its data lost with respect to the rest of the program.
The reason I mention thread safety is that I personally have encountered many bugs related to singletons being used in multithreaded apps in unsafe ways. So only have singleton creation be thread unsafe when you are absolutely sure it won't be an issue.
In terms of how to implement it in a thread safe way I have seen it one of two says:
// first way
+ (Deck *)instance {
static dispatch_once_t onceToken;
static Deck *_shared;
dispatch_once(&onceToken, ^{
_shared = [[Deck alloc] init];
});
return _shared;
}
// second way
+ (Deck *)instance {
static Deck *_shared;
@synchronized(self) {
if (_shared == nil) {
_shared = [[Deck alloc] init];
}
}
return _shared;
}
// init method
- (id)init {
if ((self = [super init])) {
// init stuff
}
return self;
}
Using dispatch_once
requires libdispatch which means a minimum OS of iOS 4.0 or OS X 10.6. Using the @synchronized(self)
should work on OSes prior to that.