Reputation: 28473
I just did an Analyze of code that I use from a public library, and XCode pointed out a problem with the line that begins with [[[self alloc]:
static MyClass *_sharedInstance = nil;
+ (MyClass*)sharedInstance
{
if (_sharedInstance != nil) {
return _sharedInstance;
}
@synchronized(self) {
if (_sharedInstance == nil) {
[[[self alloc] init] autorelease];
}
}
return _sharedInstance;
}
As I look at this line, I have no idea how it is possible for _sharedInstance to ever get assigned. Can anyone explain to me why this code works? I would have expected that you need to write:
_sharedInstance = [[[self alloc] init] autorelease];
Upvotes: 0
Views: 105
Reputation: 162722
This is yet another example of way overthinking a +sharedInstance
method to the point where it is confusing, at best, and only works because of other shenanigans (like overriding release
).
Just do this and be done with it:
+ (id)sharedInstance
{
static MyClass *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Simple, straightforward, and does not preclude using MyClass
as a non-singleton. The one flaw in this is if +sharedInstance
is called recursively, it'll deadlock, but +sharedInstance
recursively is generally a bad sign anyway.
Upvotes: 3
Reputation: 81868
It might be set in alloc
, rather than init. This would prevent creation of another instance in a recursive call from within init
.
Explanation:
It's common for complex singletons to do a lot of setup. This setup could be complex, touching more than only this class. It happens that the singleton is requested from (deep) within this setup. If the _sharedInstance
variable would not be set before calling init
, two instances would be created.
Upvotes: 0