views:

31813

answers:

18

Mine is merely (or a close variant thereof):

static MyClass *gInstance = NULL;

+ (MyClass *)instance
{
@synchronized(self)
    {
    if (gInstance == NULL)
        gInstance = [[self alloc] init];
    }
return(gInstance);
}
+6  A: 
@interface MySingleton : NSObject
{
}

+ (MySingleton *)sharedSingleton;
@end

@implementation MySingleton

+ (MySingleton *)sharedSingleton
{
  static MySingleton *sharedSingleton;

  @synchronized(self)
  {
    if (!sharedSingleton)
      sharedSingleton = [[MySingleton alloc] init];

    return sharedSingleton;
  }
}

@end

[Source]

Ben Hoffstein
This is all you should usually use for singletons. Among other things, keeping your classes separately instantiable makes them easier to test, because you can test separate instances instead of having a way to reset their state.
Chris Hanson
+7  A: 
static MyClass *sharedInst = nil;

+ (id)sharedInstance
{
    @synchronize( self ) {
        if ( sharedInst == nil ) {
            /* sharedInst set up in init */
            [[self alloc] init];
        }
    }
    return sharedInst;
}

- (id)init
{
    if ( sharedInst != nil ) {
        [NSException raise:NSInternalInconsistencyException
            format:@"[%@ %@] cannot be called; use +[%@ %@] instead"],
            NSStringFromClass([self class]), NSStringFromSelector(_cmd), 
            NSStringFromClass([self class]),
            NSStringFromSelector(@selector(sharedInstance)"];
    } else if ( self = [super init] ) {
        sharedInst = self;
        /* Whatever class specific here */
    }
    return sharedInst;
}

/* These probably do nothing in
   a GC app.  Keeps singleton
   as an actual singleton in a
   non CG app
*/
- (NSUInteger)retainCount
{
    return NSUIntegerMax;
}

- (oneway void)release
{
}

- (id)retain
{
    return sharedInst;
}

- (id)autorelease
{
    return sharedInst;
}
I noticed that clang complains about a leak if you don't assign the result of `[[self alloc] init]` to sharedInst.
pix0r
+1  A: 

This works in a non-garbage collected environment also.

@interface MySingleton : NSObject {
}

+(MySingleton *)sharedManager;

@end


@implementation MySingleton

static MySingleton *sharedMySingleton = nil;

+(MySingleton*)sharedManager {
    @synchronized(self) {
        if (sharedMySingleton == nil) {
            [[self alloc] init]; // assignment not done here
        }
    }
    return sharedMySingleton;
}


+(id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
        if (sharedMySingleton == nil) {
            sharedMySingleton = [super allocWithZone:zone];
            return sharedMySingleton;  // assignment and return on first allocation
        }
    }
    return nil; //on subsequent allocation attempts return nil
}


-(void)dealloc {
    [super dealloc];
}

-(id)copyWithZone:(NSZone *)zone {
    return self;
}


-(id)retain {
    return self;
}


-(unsigned)retainCount {
    return UINT_MAX;  //denotes an object that cannot be release
}


-(void)release {
    //do nothing    
}


-(id)autorelease {
    return self;    
}


-(id)init {
    self = [super init];
    sharedMySingleton = self;

    //initialize here

    return self;
}

@end
lajos
+3  A: 

Per my other answer below, I think you should be doing:

+ (id)sharedFoo
{
    static dispatch_once_t once;
    static MyFoo *sharedFoo;
    dispatch_once(&once, ^ { sharedFoo = [[self alloc] init]; });
    return sharedFoo;
}
Colin Barrett
Don't bother with all of what you're doing above. Make your (hopefully extremely few) singletons separately-instantiable, and just have a shared/default method.What you've done is only necessary if you really, truly, ONLY want a single instance of your class. Which you don't, esp. for unit tests.
Chris Hanson
The thing is this is the Apple sample code for "creating a singleton". But yeah, you're absolutely right.
Colin Barrett
The Apple sample code is correct if you want a "true" singleton (i.e. an object that can only be instantiated once, ever) but as Chris says, this is rarely what you want or need whereas some kind of settable shared instance is what you usually want.
Luke Redpath
+63  A: 

Here's a wiki version people can edit, based on schwa's original (now revised to include more methods, based on Apple's recommendations for Singletons):

static MySingleton *sharedInstance = nil;

@implementation MySingleton

#pragma mark -
#pragma mark class instance methods

#pragma mark -
#pragma mark Singleton methods

+ (MySingleton*)sharedInstance
{
    @synchronized(self)
    {
     if (sharedInstance == nil)
      sharedInstance = [[MySingleton alloc] init];
    }
    return sharedInstance;
}

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [super allocWithZone:zone];
            return sharedInstance;  // assignment and return on first allocation
        }
    }
    return nil; // on subsequent allocation attempts return nil
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)retain {
    return self;
}

- (unsigned)retainCount {
    return UINT_MAX;  // denotes an object that cannot be released
}

- (void)release {
    //do nothing
}

- (id)autorelease {
    return self;
}

@end
Colin Barrett
Is there any need to think about releasing gInstance? If you for an example uses the singleton pattern in an iphone application.
ullmark
@Markus Singletons in Objective C are usually intended to live from instantiation until the memory is reclaimed by the OS when the process terminates.
Gregory Higley
Is there a reason `sharedInstance` is assigned in `-allocWithZone:` and in `+sharedInstance`?
Sidnicious
+15  A: 

Another option is to use the +(void)initialize method. From the documentation:

"The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses."

So you could do something akin to this:

static MySingleton *sharedSingleton;

+ (void)initialize
{
    static BOOL initialized = NO;
    if(!initialized)
    {
        initialized = YES;
        sharedSingleton = [[MySingleton alloc] init];
    }
}
Robbie Hanson
If the runtime will only ever call this once, what does the BOOL do? Is that a precaution in case someone calls this function explicitly from their code?
Aftermathew
Yes, it is a precaution since the function can also be called directly.
Robbie Hanson
This also is **required** because there could be subclasses. If they don’t override `+initialize` their superclasses implementation will be called if the subclass is first used.
Sven
What happens if someone inadvertently releases this instance? They effectively deallocate it for the entire process. I think the standard method that overrides the copy/release/autorelease methods is more reliable.
Paul Alexander
+1  A: 

A thorough explanation of the Singleton macro code is on the blog Cocoa With Love

http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html.

M@

Matthieu Cormier
A: 

I usually use code roughly similar to that in Ben Hoffstein's answer (which I also got out of Wikipedia). I use it for the reasons stated by Chris Hanson in his comment.

However, sometimes I have a need to place a singleton into a NIB, and in that case I use the following:

@implementation Singleton

static Singleton *singleton = nil;

- (id)init {
    static BOOL initialized = NO;
    if (!initialized) {
        self = [super init];
        singleton = self;
        initialized = YES;
    }
    return self;
}

+ (id)allocWithZone:(NSZone*)zone {
    @synchronized (self) {
        if (!singleton)
            singleton = [super allocWithZone:zone];  
    }
    return singleton;
}

+ (Singleton*)sharedSingleton {
    if (!singleton)
        [[Singleton alloc] init];
    return singleton;
}

@end

I leave the implementation of -retain (etc.) to the reader, although the above code is all you need in a garbage collected environment.

Gregory Higley
Your code is not thread-safe. It uses synchronized in the alloc method, but not in the init method. Checking on the initialized bool is not thread-safe.
Mecki
+7  A: 

You can optimize the access to the instance by synchronizing only if it's really needed. If gInstance is alread initialized, we don't have to take the lock.

static MyClass *gInstance = NULL;

+ (MyClass *)sharedMyClass
{ 
    if(gInstance)
        return gInstance;

    @synchronized(self)
    {
        if (gInstance == NULL)
            gInstance = [[self alloc] init];
    }
    return gInstance;
}
nschmidt
The optimization already made a big difference in actual code. Avoiding the synchronization can be a big win, if you lazily call sharedMyClass on every access to the shared instance.
nschmidt
@nschmidt - If you bail early with `if(gInstance) return gInstance;` you don't later need to check `if(gInstance == NULL)` - you can assume that one is true. The compiler probably does that optimization, but it'll make your code clearer too, so go ahead and do that.
Chris Lutz
@Chris Lutz: If I don't check for gInstance to be NULL, two threads could come along and both create an instance.
nschmidt
The double-checked locking technique used here is often a real problem in some environments (see http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf or Google it). Until shown otherwise, I'd assume that Objective-C isn't immune. Also see http://www.wincent.com/a/knowledge-base/archives/2006/01/locking_doublec.php.
Steve Madsen
If you do that, then there is no point in using synchronization at all.
Marius
A: 

You don't want to synchronize on self... Since the self object doesn't exist yet! You end up locking on a temporary id value. You want to ensure that no one else can run class methods ( sharedInstance, alloc, allocWithZone:, etc ), so you need to synchronize on the class object instead:

@implementation MYSingleton

static MYSingleton * sharedInstance = nil;

+( id )sharedInstance {
    @synchronized( [ MYSingleton class ] ) {
        if( sharedInstance == nil )
            sharedInstance = [ [ MYSingleton alloc ] init ];
    }

    return sharedInstance;
}

+( id )allocWithZone:( NSZone * )zone {
    @synchronized( [ MYSingleton class ] ) {
        if( sharedInstance == nil )
            sharedInstance = [ super allocWithZone:zone ];
    }

    return sharedInstance;
}

-( id )init {
    @synchronized( [ MYSingleton class ] ) {
        self = [ super init ];
        if( self != nil ) {
            // Insert initialization code here
        }

        return self;
    }
}

@end
Rob Dotson
The rest of the methods, accessor methods, mutator methods, etc should synchronize on self. All class(+) methods and initializers (and probably -dealloc) should synchronize on the class object. You can avoid having to manually sync if you use Objective-C 2.0 properties instead of accessor/mutator methods. All object.property and object.property = foo, are automatically synchronized to self.
Rob Dotson
Please explain why you think that the `self` object doesn't exist in a class method. The runtime determines which method implementation to invoke based on the exact same value that it provides as `self` to every method (class or instance).
dreamlax
In a class method of `MYSingleton` `self` and `[MYSingleton class]` are the same. If you don’t believe me do this experiment: `NSAssert( self == [MYSingleton class], @"OK, so Sven was wrong" );`
Sven
+2  A: 

I have an interesting variation on sharedInstance that is thread safe, but does not lock after the initialization. I am not yet sure enough of it to modify the top answer as requested, but I present it for further discussion:

// Volatile to make sure we are not foiled by CPU caches
static volatile ALBackendRequestManager *sharedInstance;

// There's no need to call this directly, as method swizzling in sharedInstance
// means this will get called after the singleton is initialized.
+ (MySingleton *)simpleSharedInstance
{
    return (MySingleton *)sharedInstance;
}

+ (MySingleton*)sharedInstance
{
    @synchronized(self)
    {
        if (sharedInstance == nil)
        {
            sharedInstance = [[MySingleton alloc] init];
            // Replace expensive thread-safe method 
            // with the simpler one that just returns the allocated instance.
            SEL origSel = @selector(sharedInstance);
            SEL newSel = @selector(simpleSharedInstance);
            Method origMethod = class_getClassMethod(self, origSel);
            Method newMethod = class_getClassMethod(self, newSel);
            method_exchangeImplementations(origMethod, newMethod);
        }
    }
    return (MySingleton *)sharedInstance;
}
Kendall Helmstetter Gelner
+1 that's really intriguing. I might use `class_replaceMethod` to transform `sharedInstance` into a clone of `simpleSharedInstance`. That way you wouldn't ever have to worry about acquiring an `@synchronized` lock again.
Dave DeLong
It's the same effect, using exchangeImplementations means that after init when you call sharedInstance, you are really calling simpleSharedInstance. I actually started out with replaceMethod, but decided it was better to just switch the implementations around so the original still existed if needed...
Kendall Helmstetter Gelner
In further testing, I could not get replaceMethod to work - in repeated calls, the code still called the original sharedInstance instead of simpleSharedInstance. I think it may be because they are both class level methods... The replace I used was: class_replaceMethod(self, origSel, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)); and some variations thereof. I can verify the code I have posted works and simpleSharedInstance is called after the first pass through sharedInstance.
Kendall Helmstetter Gelner
You can make a thread safe version that does not pay locking costs after initialization without doing a bunch of runtime mucking, I have posted an implementation below.
Louis Gerbarg
+1 great idea. I just love those things one can do with the runtime. But in most cases this probably is premature optimization. If I’d really have to get rid of the synchronization cost I’d probably use the lockless version by Louis.
Sven
A: 

Here's a macro that I put together:

http://github.com/cjhanson/Objective-C-Optimized-Singleton

It is based on the work here by Matt Gallagher But changing the implementation to use method swizzling as described here by Dave MacLachlan of Google.

I welcome comments / contributions.

CJ Hanson
the link seems broken - where can I get that source?
amok
+13  A: 

Since Kendall posted a threadsafe singleton that attempts to avoid locking costs, I thought I would toss one up as well:

static void * volatile sharedInstance = nil;                                                

+ (className *) sharedInstance {                                                                    
  while (!sharedInstance) {                                                                          
    className *temp = [[self alloc] init];                                                                 
    if(!OSAtomicCompareAndSwapPtrBarrier(0x0, temp, &sharedInstance)) {
      [temp release];                                                                                   
    }                                                                                                    
  }                                                                                                        
  return sharedInstance;                                                                        
}

Okay, let me explain how this works:

  1. Fast case: In normal execution sharedInstance has already been set, so the while loop is never executed and the function returns after simply testing for the variables existence
  2. Slow case: If shared instance doesn't existence then an instance is allocated and copied into sharedInstance using a CAS
  3. Contended case: If two threads both attempt to call sharedInstance at the same time AND sharedInstance doesn't exist at the same time then they will both initialize new instances of the singleton and attempt to CAS it into position. Whichever one wins the CAS returns immediately, whichever one loses releases the instance it just allocated and returns the (now set) sharedInstance. The single OSAtomicCompareAndSwapPtrBarrier acts as both a write barrier for the setting thread and a read barrier from the testing thread.
Louis Gerbarg
This is complete overkill for the at-most one time it can happen during an application's lifetime. Nevertheless, it is spot-on correct, and the compare-and-swap technique is a useful tool to know about, so +1.
Steve Madsen
A: 

Shouln't this be threadsafe and avoid the expensive locking after the first call?

+ (MySingleton*)sharedInstance
{
    if (sharedInstance == nil) {
        @synchronized(self) {
            if (sharedInstance == nil) {
                sharedInstance = [[MySingleton alloc] init];
            }
        }
    }
    return (MySingleton *)sharedInstance;
}
Jompe
The double-checked locking technique used here is often a real problem in some environments (see http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf or Google it). Until shown otherwise, I'd assume that Objective-C isn't immune. Also see http://www.wincent.com/a/knowledge-base/archives/2006/01/locking_doublec.php.
Steve Madsen
A: 

For an in-depth discussion of the singleton pattern in Objective-C, look here:

http://www.duckrowing.com/2010/05/21/using-the-singleton-pattern-in-objective-c/

Fred McCann
A: 

static mySingleton *obj=nil;

@implementation mySingleton

-(id) init { if(obj != nil){
[self release]; return obj; } else if(self = [super init]) { obj = self; }
return obj; }

+(mySingleton*) getSharedInstance { @synchronized(self){ if(obj == nil) { obj = [[mySingleton alloc] init]; } } return obj; }

  • (id)retain { return self; }

  • (id)copy { return self; }

  • (unsigned)retainCount { return UINT_MAX; // denotes an object that cannot be released }

  • (void)release { if(obj != self){ [super release]; } //do nothing }

  • (id)autorelease { return self; }

-(void) dealloc { [super dealloc]; } @end

A: 

I made a reusable singleton class from which you can inherit to get singleton properties. You can see source code here: http://www.devbypractice.com/reusable-singleton-class-in-objective-c-for-iphone-and-ipad/

jey350
+2  A: 

With dispatch, you can also give this a shot:

+ (id)sharedFoo
{
    static dispatch_once_t once;
    static MyFoo *sharedFoo;
    dispatch_once(&once, ^ { sharedFoo = [[self alloc] init]; });
    return sharedFoo;
}
Colin Barrett