I found some information in the net to create a singleton class using GCD. Thats cool because it's thread-safe with very low overhead. Sadly I could not find complete solutions but only snippets of the sharedInstance method. So I made my own class using the trial and error method - and et voila - the following came out:
@implementation MySingleton
// MARK: -
// MARK: Singleton Pattern using GCD
+ (id)allocWithZone:(NSZone *)zone { return [[self sharedInstance] retain]; }
- (id)copyWithZone:(NSZone *)zone { return self; }
- (id)autorelease { return self; }
- (oneway void)release { /* Singletons can't be released */ }
- (void)dealloc { [super dealloc]; /* should never be called */ }
- (id)retain { return self; }
- (NSUInteger)retainCount { return NSUIntegerMax; /* That's soooo non-zero */ }
+ (MySingleton *)sharedInstance
{
static MySingleton * instance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
// --- call to super avoids a deadlock with the above allocWithZone
instance = [[super allocWithZone:nil] init];
});
return instance;
}
// MARK: -
// MARK: Initialization
- (id)init
{
self = [super init];
if (self)
{
// Initialization code here.
}
return self;
}
@end
Please feel free to comment and tell me if I've missing something or doing something completely wrong ;)
Cheers Stefan
Keep it simple:
+(instancetype)sharedInstance
{
static dispatch_once_t pred;
static id sharedInstance = nil;
dispatch_once(&pred, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (void)dealloc
{
// implement -dealloc & remove abort() when refactoring for
// non-singleton use.
abort();
}
That is it. Overriding retain
, release
, retainCount
and the rest is just hiding bugs and adding a bunch of lines of unnecessary code. Every line of code is a bug waiting to happen. In reality, if you are causing dealloc
to be called on your shared instance, you have a very serious bug in your app. That bug should be fixed, not hidden.
This approach also lends itself to refactoring to support non-singleton usage modes. Pretty much every singleton that survives beyond a few releases will eventually be refactored into a non-singleton form. Some (like NSFileManager
) continue to support a singleton mode while also supporting arbitrary instantiation.
Note that the above also "just works" in ARC.