Please find below the Objective-C code snippet I am using, for proper thread-safe singleton implementation
header file :
/*
*
* Singleton interface that match Cocoa recommendation
* @ http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32
* extended with thread-safe pattern
*/
@interface MyCustomManager : NSObject {
}
#pragma mark Singleton Thred-Safe Pattern
+ (MyCustomManager *) sharedInstance;
+ (id)allocWithZone:(NSZone *)zone;
- (id)copyWithZone:(NSZone *)zone;
- (id)retain;
- (NSUInteger)retainCount;
- (void)release;
- (id)autorelease;
#pragma mark -
implementation file :
/*
* My custom manager Class singleton implementation
*/
@implementation MyCustomManager
#pragma mark Initializers
/*
* specific initialize goes here
*/
- (void) specificInitialize
{
// ...
}
/*
* Ensure any owned object is properly released
*/
- (void) dealloc
{
[super dealloc];
}
#pragma mark -
#pragma mark Singleton Thred-Safe Pattern
//- use Volatile to make sure we are not foiled by CPU caches
static void * volatile sharedInstance = nil;
/*
* retrieve sharedInstance based on OSAtomicCompareAndSwapPtrBarrier that
* acts as both a write barrier for the setting thread and a read barrier from the testing thread
* more info @ http://stackoverflow.com/questions/145154/what-does-your-objective-c-singleton-look-like/2449664#2449664
* and http://stackoverflow.com/questions/6915/thread-safe-lazy-contruction-of-a-singleton-in-c/6943#6943
*/
+ (MyCustomManager *) sharedInstance {
//- check sharedInstance existenz
while (!sharedInstance) {
//- create a temporary instance of the singleton
id temp = [super allocWithZone:NSDefaultMallocZone()];
//- The OSAtomicCompareAndSwapPtrBarrier function provided on Mac OS X
//- checks whether sharedInstance is NULL and only actually sets it to temp to it if it is.
//- This uses hardware support to really, literally only perform the swap once and tell whether it happened.
if(OSAtomicCompareAndSwapPtrBarrier(0x0, (void *)temp, &sharedInstance)) {
//- compute singleton initialize
MyCustomManager *singleton = (MyCustomManager *) sharedInstance;
[singleton specificInitialize];
}
else {
//- if the swap didn't take place, delete the temporary instance
[temp release];
temp = nil;
}
}
//- return computed sharedInstance
return sharedInstance;
}
/*
* method to ensure that another instance is not allocated if someone tries to allocate
* and initialize an instance of your class directly instead of using the class factory method.
* Instead, it just returns the shared object.
*/
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedInstance] retain];
}
/*
* Implements the base protocol methods to do the appropriate things to ensure singleton status.
* Applies to memory-managed code, not to garbage-collected code
*/
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
/*
* Implements the base protocol methods to do the appropriate things to ensure singleton status.
* Applies to memory-managed code, not to garbage-collected code
*/
- (id)retain
{
return self;
}
/*
* Implements the base protocol methods to do the appropriate things to ensure singleton status.
* Applies to memory-managed code, not to garbage-collected code
*/
- (NSUInteger)retainCount
{
return NSUIntegerMax; //denotes an object that cannot be released
}
/*
* Implements the base protocol methods to do the appropriate things to ensure singleton status.
* Applies to memory-managed code, not to garbage-collected code
*/
- (void)release
{
//do nothing
}
/*
* Implements the base protocol methods to do the appropriate things to ensure singleton status.
* Applies to memory-managed code, not to garbage-collected code
*/
- (id)autorelease
{
return self;
}
#pragma mark -
Just to help you starting in objective-c and not get lost in your project structure, you can consider having the project structure matching your file system so as your project becomes bigger you won't get lost.
Also please consider using a proper class naming convention, and stick to it.
I a providing you mine as sample:
Any class that match singleton pattern is named using Manager suffix (E.g. MyCustomManager ).
Any static class is named using Helper suffix (E.g. MyCustomHelper).
Any class dedicated to control particular process is named using Controller suffix ( E.g. MyParticularTaskConstroller ).
Any UI control that inherit from another control needs provide control suffix ( E.g. MyCustomDetailCell inheriting from UITableViewCell )
Hope this helps.