333

My singleton accessor method is usually some variant of:

static MyClass *gInstance = NULL;

+ (MyClass *)instance
{
    @synchronized(self)
    {
        if (gInstance == NULL)
            gInstance = [[self alloc] init];
    }

    return(gInstance);
}

What could I be doing to improve this?

Rachel
  • 130,264
  • 66
  • 304
  • 490
schwa
  • 11,962
  • 14
  • 43
  • 54
  • 27
    What you have is fine, though you could move the global variable declaration into your +instance method (the only place it needs to be used, unless you're allowing it to be set as well) and use a name like +defaultMyClass or +sharedMyClass for your method. +instance isn't intention-revealing. – Chris Hanson Sep 28 '08 at 09:37
  • Since it's unlikely the 'answer' to this question will change any time soon, I'm placing a historical lock on the question. Two reasons 1) Lots of views, votes, and good content 2) To prevent yo-yoing of open/closed. It was a great question for its time, but questions of these types are not appropriate for Stack Overflow. We now have [Code Review](http://codereview.stackexchange.com) for checking working code. Please take all discussion of this question to [this meta question](http://meta.stackexchange.com/questions/141006). – George Stocker Mar 21 '13 at 19:52

26 Answers26

207

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];
    }
}
jscs
  • 63,694
  • 13
  • 151
  • 195
Robbie Hanson
  • 3,259
  • 1
  • 21
  • 16
  • 7
    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 Apr 03 '09 at 17:28
  • 5
    Yes, it is a precaution since the function can also be called directly. – Robbie Hanson Apr 08 '09 at 04:32
  • 33
    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 Sep 06 '10 at 21:25
  • 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 Oct 23 '10 at 14:18
  • 1
    I prefer the initialize method myself. That way I can write a simple method getSingleton that can simply return the singleton reference. But why can't your initialize method simply test the singleton reference for nil instead of setting up another boolean? – Marvo Jan 30 '11 at 00:56
  • 1
    Yes, it could simply check to see if sharedSingleton is nil. This is just boilerplate code that would allow you to do other things in the initialize method, such as initialize other static variables. – Robbie Hanson Mar 25 '11 at 15:31
  • 3
    @Paul you can override the `release` method and make it empty. :) –  Mar 25 '11 at 22:20
  • Argh this is horrible, just use Synchronized, that makes the block of code accessible by 1 thread at a time. – aryaxt Apr 01 '11 at 00:31
  • 4
    @aryaxt: From the docs listed, this is already thread safe. So, the call is once per runtime -- period. This would seem to be the correct, thread-safe, optimally efficient solution. – lilbyrdie Jun 23 '11 at 13:52
  • 3
    What about [Creating a Singleton Instance in the documention](http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32)? – JJD Aug 29 '11 at 13:23
  • 2
    @JJD: The Apple example is for creating transparently strict singletons, which is almost never appropriate. The majority of singletons are for convenience, not requirement (there may be more than one, there just usually isn't; e.g. NSNotificationCenter). For classes that *must* be singletons, it is usually a programming error to create multiple instances and you should assert in `init` rather than "fix" the caller's mistake. The only time Apple's example makes sense is when the singleton is an implementation detail that the caller can ignore. At a minimum, the class should be immutable. – Rob Napier Sep 09 '11 at 14:45
  • In the example above-- why is the init function not actually called on the object? For example in my singleton class, I used to have the old non-thread-safe implementation and am trying to fix it. Log statements show that when implementing the initialize function as above, the - (id)init function of the singleton class is never called. – ch3rryc0ke Apr 10 '12 at 23:13
  • 1
    IMHO initialize is pretty well useless. You have very little control over the when (order might be important but you don't realize that until it changes on you, for example). Also the subclass problem... Also you need multiple methods to deal with the singleton.. – Tom Andersen May 17 '12 at 13:20
  • You could also use `self`, rather than `MySingleton`, this would eliminate the need of subclassing `+ (void)initialize` in subclasses. => `sharedSingleton = [[self alloc] init];` – IluTov Dec 23 '12 at 18:33
  • Note that `+initialize` is called the first time a message is sent to the class or a subclass. So in particular, if you try to access `sharedSingleton` without calling any class methods, you'll get `nil` unless you send a dummy message (e.g. `(void)[MySingleton class];`) first. – Adam Rosenfield Dec 24 '12 at 21:36
95
@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
  • 102,129
  • 8
  • 104
  • 120
  • 7
    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 Sep 28 '08 at 09:36
  • Is it OK to leave out the @syncronised if you don't store any data in the singleton? – Stig Brautaset May 12 '11 at 15:10
  • 3
    Stig Brautaset: No, it is not okay to leave out the @synchronized in this example. It is there to handle the possible race-condition of two threads executing this static function at the same time, both getting past the "if(!sharedSingleton)" test at the same time, and thus resulting in two [MySingleton alloc]s... The @synchronized {scope block} forces that hypothetical second thread to wait for the first thread to exit the {scope block} before being allowed to proceed into it. I hope this helps! =) – MechEthan Jul 13 '11 at 16:29
  • 3
    What stops someone from still making their own instance of the object? `MySingleton *s = [[MySingelton alloc] init];` – lindon fox Oct 28 '11 at 05:31
  • Sorry, answering my own question... – lindon fox Oct 28 '11 at 12:24
  • 1
    @lindonfox What is the answer to your question? – Raffi Khatchadourian Dec 20 '11 at 21:48
  • That's interesting how `self` is available in a class method. I assume that `self` refers to the class instance. Is that correct? – Raffi Khatchadourian Dec 20 '11 at 22:57
  • 1
    @Raffi - sorry I think I must have forgot to paste in my answer. Anyway, I got the book `Pro Objective-C Design Patterns for iOS` and it spells out how you make a "strict" singelton. Basically since you can't make the initiating methods private, you need to override the methods alloc and copy. So if you try and do something like `[[MySingelton alloc] init]` you will get a run time error (though not a compile time error unfortunately). I don't understand how all the details of the object creation, but you implement `+ (id) allocWithZone:(NSZone *)zone` which is called in `sharedSingleton` – lindon fox Dec 21 '11 at 03:42
  • While this solution is correct, the use of `@synchronized` bothers me as [it is horribly slow](http://perpendiculo.us/?p=133). – DarkDust Apr 17 '12 at 08:00
59

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
  • 4,451
  • 1
  • 26
  • 33
  • 6
    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 Sep 28 '08 at 09:35
  • The thing is this is the Apple sample code for "creating a singleton". But yeah, you're absolutely right. – Colin Barrett Oct 23 '08 at 01:39
  • 1
    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 Jul 25 '09 at 01:25
  • Here is a macro for the above method: https://gist.github.com/1057420. This is what I use. – Kobski Jan 30 '12 at 19:21
  • 1
    Unit tests aside, there's nothing speaking against this solution, correct? And it's fast and safe. – CodeSmile Apr 06 '12 at 20:19
58

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

#import <libkern/OSAtomic.h>

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 variable's existence;

  2. Slow case: If sharedInstance doesn't exist, then an instance is allocated and copied into it using a Compare And Swap ('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.

Community
  • 1
  • 1
Louis Gerbarg
  • 43,356
  • 8
  • 80
  • 90
  • 18
    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 Apr 22 '10 at 14:37
  • Nice answer - the OSAtomic family is a good thing to know about – Bill Feb 27 '11 at 01:24
  • 1
    @Louis: Amazing, really enlightening answer! One question though: what should my `init` method do in your approach? Throwing an exception when `sharedInstance` is initialized is not a good idea, I believe. What to do then to prevent user calling `init` directly many times? – matm Sep 01 '11 at 16:39
  • 2
    I generally don't prevent it. There are often valid reasons to allow what is generally a singleton to multiply instantiated, the most commons is for certain types of unit testing. If I really wanted to enforce a single instance I would probably have the init method check to see if the global existed, and if it did I have it release self and return the global. – Louis Gerbarg Sep 02 '11 at 03:57
  • Hmm, why is the `volatile` qualification here necessary? Since sharedInstance is only initialized once how come we are preventing compiler from caching it in register by using `volatile`? – Tony Dec 29 '11 at 17:37
  • 1
    @Tony bit late of response, but OSAtomicCompareAndSwapPtrBarrier requires a volatile. Perhaps the volatile keyword is to keep the compiler from optimizing away the check? See: http://stackoverflow.com/a/5334727/449161 and https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/OSAtomicCompareAndSwapPtrBarrier.3.html – Ben Flynn Nov 16 '12 at 18:23
14
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;
}
  • 3
    I noticed that clang complains about a leak if you don't assign the result of `[[self alloc] init]` to sharedInst. – pix0r May 06 '09 at 18:21
  • Subverting init like this is a pretty ugly approach IMO. Don't mess with init and/or the actual creation of the object. If you instead go for a controlled point of access to a shared instance, while not hard-baking singleton into the object, you'll have a happier time later if writing tests etc. Hard singletons are far too overused. – occulus Jan 14 '13 at 13:41
12

Edit: This implementation obsoleted with ARC. Please have a look at How do I implement an Objective-C singleton that is compatible with ARC? for correct implementation.

All the implementations of initialize I've read in other answers share a common error.

+ (void) initialize {
  _instance = [[MySingletonClass alloc] init] // <----- Wrong!
}

+ (void) initialize {
  if (self == [MySingletonClass class]){ // <----- Correct!
      _instance = [[MySingletonClass alloc] init] 
  }
}

The Apple documentation recommend you check the class type in your initialize block. Because subclasses call the initialize by default. There exists a non-obvious case where subclasses may be created indirectly through KVO. For if you add the following line in another class:

[[MySingletonClass getInstance] addObserver:self forKeyPath:@"foo" options:0 context:nil]

Objective-C will implicitly create a subclass of MySingletonClass resulting in a second triggering of +initialize.

You may think that you should implicitly check for duplicate initialization in your init block as such:

- (id) init { <----- Wrong!
   if (_instance != nil) {
      // Some hack
   }
   else {
      // Do stuff
   }
  return self;
}

But you will shoot yourself in the foot; or worse give another developer the opportunity to shoot themselves in the foot.

- (id) init { <----- Correct!
   NSAssert(_instance == nil, @"Duplication initialization of singleton");
   self = [super init];
   if (self){
      // Do stuff
   }
   return self;
}

TL;DR, here's my implementation

@implementation MySingletonClass
static MySingletonClass * _instance;
+ (void) initialize {
   if (self == [MySingletonClass class]){
      _instance = [[MySingletonClass alloc] init];
   }
}

- (id) init {
   ZAssert (_instance == nil, @"Duplication initialization of singleton");
   self = [super init];
   if (self) {
      // Initialization
   }
   return self;
}

+ (id) getInstance {
   return _instance;
}
@end

(Replace ZAssert with our own assertion macro; or just NSAssert.)

Community
  • 1
  • 1
lorean
  • 2,150
  • 19
  • 25
10

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.

Matthieu Cormier
  • 2,185
  • 1
  • 21
  • 32
9

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
  • 74,769
  • 26
  • 128
  • 150
  • 1
    +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 Feb 19 '10 at 06:19
  • 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 Feb 19 '10 at 07:46
  • 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 Feb 19 '10 at 07:58
  • 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 Mar 15 '10 at 18:57
  • 1
    +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 Sep 06 '10 at 21:35
  • Time has moved on, and Apple now has a better way to set up singletons using GCD... so others may want to look for that. Of course if you have to support pre-iOS4 stuff still... – Kendall Helmstetter Gelner Jun 22 '11 at 17:53
  • @KendallHelmstetterGelner, you refer to `dispatch_once`? – i_am_jorf Mar 06 '13 at 21:49
  • Yes, exactly, dispatch_once. It's what I use pretty much all the time now if I want a singleton. – Kendall Helmstetter Gelner Mar 06 '13 at 21:53
6

Short answer: Fabulous.

Long answer: Something like....

static SomeSingleton *instance = NULL;

@implementation SomeSingleton

+ (id) instance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (instance == NULL){
            instance = [[super allocWithZone:NULL] init];
        }
    });
    return instance;
}

+ (id) allocWithZone:(NSZone *)paramZone {
    return [[self instance] retain];
}

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

- (id) autorelease {
    return self;
}

- (NSUInteger) retainCount {
    return NSUIntegerMax;
}

- (id) retain {
    return self;
}

@end

Be sure to read the dispatch/once.h header to understand what's going on. In this case the header comments are more applicable than the docs or man page.

quellish
  • 21,123
  • 4
  • 76
  • 83
5

I've rolled singleton into a class, so other classes can inherit singleton properties.

Singleton.h :

static id sharedInstance = nil;

#define DEFINE_SHARED_INSTANCE + (id) sharedInstance {  return [self sharedInstance:&sharedInstance]; } \
                               + (id) allocWithZone:(NSZone *)zone { return [self allocWithZone:zone forInstance:&sharedInstance]; }

@interface Singleton : NSObject {

}

+ (id) sharedInstance;
+ (id) sharedInstance:(id*)inst;

+ (id) allocWithZone:(NSZone *)zone forInstance:(id*)inst;

@end

Singleton.m :

#import "Singleton.h"


@implementation Singleton


+ (id) sharedInstance { 
    return [self sharedInstance:&sharedInstance];
}

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

+ (id) allocWithZone:(NSZone *)zone forInstance:(id*)inst {
    @synchronized(self) {
        if (*inst == nil) {
            *inst = [super allocWithZone:zone];
            return *inst;  // 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

And here is an example of some class, that you want to become singleton.

#import "Singleton.h"

@interface SomeClass : Singleton {

}

@end

@implementation SomeClass 

DEFINE_SHARED_INSTANCE;

@end

The only limitation about Singleton class, is that it is NSObject subclass. But most time I use singletons in my code they are in fact NSObject subclasses, so this class really ease my life and make code cleaner.

obscenum
  • 51
  • 1
  • 3
  • You might want to use some other locking mechanism because [`@synchronized` is horribly slow](http://perpendiculo.us/?p=133) and should be avoided. – DarkDust Apr 17 '12 at 08:04
2

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
Dana
  • 32,083
  • 17
  • 62
  • 73
lajos
  • 25,525
  • 19
  • 65
  • 75
2

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
  • 823
  • 8
  • 17
2

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
  • 21
  • 1
  • 2
    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 Apr 22 '10 at 15:04
2

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

Using the Singleton Pattern in Objective-C

2

How about

static MyClass *gInstance = NULL;

+ (MyClass *)instance
{
    if (gInstance == NULL) {
        @synchronized(self)
        {
            if (gInstance == NULL)
                gInstance = [[self alloc] init];
        }
    }

    return(gInstance);
}

So you avoid the synchronization cost after initialization?

Tony
  • 36,591
  • 10
  • 48
  • 83
1

KLSingleton is:

  1. Subclassible (to the n-th degree)
  2. ARC compatible
  3. Safe with alloc and init
  4. Loaded lazily
  5. Thread-safe
  6. Lock-free (uses +initialize, not @synchronize)
  7. Macro-free
  8. Swizzle-free
  9. Simple

KLSingleton

kevinlawler
  • 930
  • 1
  • 9
  • 19
  • 1
    I'm using your NSSingleton for my project, and It seems to be incompatible with KVO. The matter is that KVO creates subclass for every KVO object with prefixing it NSKVONotifying_*MyClass*. And it makes MyClass +initialize and -init methods to be called twice. – Oleg Trakhman Jul 03 '12 at 18:28
  • I tested this on the latest Xcode and didn't have any trouble registering for or receiving KVO events. You can verify this with the following code: https://gist.github.com/3065038 As I mentioned on Twitter, the +initialize methods are called once for NSSingleton and once for each subclass. This is a property of Objective-C. – kevinlawler Jul 07 '12 at 06:19
  • If you add `NSLog(@"initialize: %@", NSStringFromClass([self class]));` to the `+initialize` method you can verify that the classes are initialized only once. – kevinlawler Jul 07 '12 at 06:24
  • NSLog(@"initialize: %@", NSStringFromClass([self class])); – Oleg Trakhman Jul 07 '12 at 10:24
  • You might want to also have it be IB compatible. Mine is: http://stackoverflow.com/questions/4609609/use-singleton-in-interface-builder – Dan Rosenstark Sep 05 '12 at 19:55
0

My way is simple like this:

static id instanceOfXXX = nil;

+ (id) sharedXXX
{
    static volatile BOOL initialized = NO;

    if (!initialized)
    {
        @synchronized([XXX class])
        {
            if (!initialized)
            {
                instanceOfXXX = [[XXX alloc] init];
                initialized = YES;
            }
        }
    }

    return instanceOfXXX;
}

If the singleton is initialized already, the LOCK block will not be entered. The second check if(!initialized) is to make sure it is not initialized yet when the current thread acquires the LOCK.

TienDC
  • 301
  • 2
  • 9
  • It's not clear that marking `initialized` as `volatile` is sufficient. See http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf. – i_am_jorf Mar 06 '13 at 21:12
0

I've not read through all the solutions, so forgive if this code is redundant.

This is the most thread safe implementation in my opinion.

+(SingletonObject *) sharedManager
{
    static SingletonObject * sharedResourcesObj = nil;

    @synchronized(self)
    {
        if (!sharedResourcesObj)
        {
            sharedResourcesObj = [[SingletonObject alloc] init];
        }
    }

    return sharedResourcesObj;
}
i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
Zolt
  • 2,761
  • 8
  • 43
  • 60
0

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
  • 1
    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 Jan 13 '10 at 22:10
  • 3
    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 Feb 19 '10 at 06:53
  • 2
    Inside of a class method, `self` _is_ the class object. Try it yourself: `#import @interface Eggbert : NSObject + (BOOL) selfIsClassObject; @end @implementation Eggbert + (BOOL) selfIsClassObject { return self == [Eggbert class]; } @end int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSLog(@"%@", [Eggbert selfIsClassObject] ? @"YES" : @"NO"); [pool drain]; return 0; }` – jscs Sep 27 '11 at 02:23
0
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
james
  • 26,141
  • 19
  • 95
  • 113
0

Just wanted to leave this here so I don't lose it. The advantage to this one is that it's usable in InterfaceBuilder, which is a HUGE advantage. This is taken from another question that I asked:

static Server *instance;

+ (Server *)instance { return instance; }

+ (id)hiddenAlloc
{
    return [super alloc];
}

+ (id)alloc
{
    return [[self instance] retain];
}


+ (void)initialize
{
    static BOOL initialized = NO;
    if(!initialized)
    {
        initialized = YES;
        instance = [[Server hiddenAlloc] init];
    }
}

- (id) init
{
    if (instance)
        return self;
    self = [super init];
    if (self != nil) {
        // whatever
    }
    return self;
}
Community
  • 1
  • 1
Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421
0

I know there are a lot of comments on this "question", but I don't see many people suggesting using a macro to define the singleton. It's such a common pattern and a macro greatly simplifies the singleton.

Here are the macros I wrote based on several Objc implementations I've seen.

Singeton.h

/**
 @abstract  Helps define the interface of a singleton.
 @param  TYPE  The type of this singleton.
 @param  NAME  The name of the singleton accessor.  Must match the name used in the implementation.
 @discussion
 Typcially the NAME is something like 'sharedThing' where 'Thing' is the prefix-removed type name of the class.
 */
#define SingletonInterface(TYPE, NAME) \
+ (TYPE *)NAME;


/**
 @abstract  Helps define the implementation of a singleton.
 @param  TYPE  The type of this singleton.
 @param  NAME  The name of the singleton accessor.  Must match the name used in the interface.
 @discussion
 Typcially the NAME is something like 'sharedThing' where 'Thing' is the prefix-removed type name of the class.
 */
#define SingletonImplementation(TYPE, NAME) \
static TYPE *__ ## NAME; \
\
\
+ (void)initialize \
{ \
    static BOOL initialized = NO; \
    if(!initialized) \
    { \
        initialized = YES; \
        __ ## NAME = [[TYPE alloc] init]; \
    } \
} \
\
\
+ (TYPE *)NAME \
{ \
    return __ ## NAME; \
}

Example of use:

MyManager.h

@interface MyManager

SingletonInterface(MyManager, sharedManager);

// ...

@end

MyManager.m

@implementation MyManager

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}

SingletonImplementation(MyManager, sharedManager);

// ...

@end

Why a interface macro when it's nearly empty? Code consistency between the header and code files; maintainability in case you want to add more automatic methods or change it around.

I'm using the initialize method to create the singleton as is used in the most popular answer here (at time of writing).

Nate
  • 12,963
  • 4
  • 59
  • 80
0

With Objective C class methods, we can just avoid using the singleton pattern the usual way, from:

[[Librarian sharedInstance] openLibrary]

to:

[Librarian openLibrary]

by wrapping the class inside another class that just has Class Methods, that way there is no chance of accidentally creating duplicate instances, as we're not creating any instance!

I wrote a more detailed blog here :)

chunkyguy
  • 3,509
  • 1
  • 29
  • 34
0

To extend the example from @robbie-hanson ...

static MySingleton* sharedSingleton = nil;

+ (void)initialize {
    static BOOL initialized = NO;
    if (!initialized) {
        initialized = YES;
        sharedSingleton = [[self alloc] init];
    }
}

- (id)init {
    self = [super init];
    if (self) {
        // Member initialization here.
    }
    return self;
}
JJD
  • 50,076
  • 60
  • 203
  • 339
-4

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
  • 15,923
  • 9
  • 67
  • 96
  • 2
    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 Jun 29 '09 at 12:44
-5

The accepted answer, although it compiles, is incorrect.

+ (MySingleton*)sharedInstance
{
    @synchronized(self)  <-------- self does not exist at class scope
    {
        if (sharedInstance == nil)
            sharedInstance = [[MySingleton alloc] init];
    }
    return sharedInstance;
}

Per Apple documentation:

... You can take a similar approach to synchronize the class methods of the associated class, using the Class object instead of self.

Even if using self works, it shouldn't and this looks like a copy and paste mistake to me. The correct implementation for a class factory method would be:

+ (MySingleton*)getInstance
{
    @synchronized([MySingleton class]) 
    {
        if (sharedInstance == nil)
            sharedInstance = [[MySingleton alloc] init];
    }
    return sharedInstance;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
deleted_user
  • 3,817
  • 1
  • 18
  • 27
  • 6
    self most certainly _does_ exist it class scope. It refers to the class instead of the instance of the class. Classes are (mostly) first class objects. – schwa Jan 25 '11 at 18:30
  • Why do you put @synchroninzed WITHIN a method? – user4951 May 04 '11 at 02:06
  • 1
    As schwa already said, `self` _is_ the class object inside of a class method. [See my comment](http://stackoverflow.com/questions/145154/what-does-your-objective-c-singleton-look-like/2060615#comment-9169201) for a snippet demonstrating this. – jscs Sep 27 '11 at 02:27
  • `self` exists, but using it as the identifier passed to `@synchronized` will synchronize access to the methods of the instance. As @user490696 points out, there are cases (like singletons) where using the class object is preferable. From The Obj-C Programming Guide: `You can take a similar approach to synchronize the class methods of the associated class, using the class object instead of self. In the latter case, of course, only one thread at a time is allowed to execute a class method because there is only one class object that is shared by all callers.` – quellish Feb 08 '12 at 19:50