Implementing a Singleton in Objective-C / iOS

John WordsworthiOS Development77 Comments

There are many pages of discussions around the internet about whether or not you should use global variables in your applications. I’m not going to to into the depths of these discussions, but I have come to live by the following ethos when it comes to using global variables in my application;

Use them sparingly; Having too many global variables floating around makes it very hard to keep track of what’s going on. I never use more than one global object for each logical section of my code – even if that object contains a handful of other objects from that section.

But you do sometimes need them; I once wrote a small game where I decided not to use my own globals at all. Truth be told, I ended up with a bit of a mess – a large number of similar constructors with a numbers of parameters to link my objects together. Sure, the units were technically separate and didn’t rely on each other – but the reality was, that when you get deep enough into your code – some classes are only ever going to be used in this project (view controllers etc).

Use them when it’s applicable; Generally, global variables are applicable in situations when you’ve got an object / class of which you are only ever going to need one of them and they don’t logically sit as a child of one single part of the application. For instance, the ‘application’ object in some languages – where the object represents the running application.

So, Singleton Eh?

The Singleton model is often used to instantiate just one instance of a class which doesn’t allow a second instance of that same class to be loaded anywhere in the application. Some implementations will throw an exception if you try to create a second instance of the class, some will create the singleton for you when you first try to access it, and some will even let you create other instances if you want, but will always manage a ‘single shared instance’ for you. Many of the core Apple classes follow this pattern, such as [UIApplication sharedApplication].

Anyway, Apple do a very good job (naturally) of providing a good example of the Singleton model. The following code is rather similar to the Apple example, but it also includes what you should have in the header file. It is also a stable part of any library of code snippets, so it has to be here really!

SingletonClass.h

#import <Foundation/Foundation.h>

@interface SingletonClass : NSObject {

}

+ (id)sharedInstance;
@end

SingletonClass.m

#import "SingletonClass.h"

@implementation SingletonClass

static SingletonClass *sharedInstance = nil;

// Get the shared instance and create it if necessary.
+ (SingletonClass *)sharedInstance {
    if (sharedInstance == nil) {
        sharedInstance = [[super allocWithZone:NULL] init];
    }

    return sharedInstance;
}

// We can still have a regular init method, that will get called the first time the Singleton is used.
- (id)init
{
    self = [super init];

    if (self) {
        // Work your initialising magic here as you normally would
    }

    return self;
}

// Your dealloc method will never be called, as the singleton survives for the duration of your app.
// However, I like to include it so I know what memory I'm using (and incase, one day, I convert away from Singleton).
-(void)dealloc
{
    // I'm never called!
    [super dealloc];
}

// We don't want to allocate a new instance, so return the current one.
+ (id)allocWithZone:(NSZone*)zone {
    return [[self sharedInstance] retain];
}

// Equally, we don't want to generate multiple copies of the singleton.
- (id)copyWithZone:(NSZone *)zone {
    return self;
}

// Once again - do nothing, as we don't have a retain counter for this object.
- (id)retain {
    return self;
}

// Replace the retain counter so we can never release this object.
- (NSUInteger)retainCount {
    return NSUIntegerMax;
}

// This function is empty, as we don't want to let the user release this object.
- (oneway void)release {

}

//Do nothing, other than return the shared instance - as this is expected from autorelease.
- (id)autorelease {
    return self;
}

@end

There you go – copy and paste this into your new project, rename the interface and implementations and you’re done – a ready to use Singleton in your project.

Making the creation of your singleton thread safe

Jiunn Harr wrote a great blog post on making the creation of your Singleton thread safe. In the above example, it is possible that your Singleton’s init method could be called more than once, if sharedInstance was called for the first and second time concurrently on different threads. In order to by-pass this problem, you can replace the sharedInstance method above with the following;

+ (SingletonClass *)sharedInstance {
    if (nil != sharedInstance) {
        return sharedInstance;
    }

    static dispatch_once_t pred;        // Lock
    dispatch_once(&pred, ^{             // This code is called at most once per app
        singleton = [[SingletonClass alloc] init];
    });

    return singleton;
}

Note. This doesn’t make all calls on your Singleton thread safe – it simply ensures that the creation of your Singleton is thread safe. This code uses Grand Central Dispatch (Cocoa and iOS4+). To read more about how this works, and why you should consider using it – check out Jiunn Haur’s great blog post on the subject.

Using the Singleton Class

The above code creates the framework for a Singleton class. You can almost ignore the majority of the code above and no go about setting up your own variables and methods for use in your singleton class. It’s worth bearing in mind that when you first attempt to you access your Singleton, it will be created for you, and from that point onwards – it will probably reside in memory for the remainder of your application’s lifecycle. Because of this, you might want to be careful about memory usage and ensure that classes inside your singleton element are tidy.

Accessing your Singleton class from your code is then simply a matter of using the +(SingletonClass*)sharedInstance to get a pointer to the one instance of the singleton class that exists in your application. You can do this anywhere in your code and you would do this for the above class by doing something like the following;

SingletonClass* sharedSingleton = [SingletonClass sharedInstance];
[sharedSingleton callAMethod];

Enjoy!

John WordsworthImplementing a Singleton in Objective-C / iOS

77 Comments on “Implementing a Singleton in Objective-C / iOS”

  1. John Wordsworth

    Hi Nick, thanks for the comment. I’ve updated the article with an additional section at the bottom which describes how you would then use this template class in a real application.

    Essentially, once you’ve added all of the Singleton gunf, you can treat this class as any other class in your codebase and add methods and variables to it as required. Then, you can access the singleton from anywhere in your code with a single line of code – this gives you a reference to the static singleton, creating it if it doesn’t already exist.

    Hope this helps.

    1. John Wordsworth

      Hehe, not a problem! Thanks for clarifying though – I just spent 5 minutes looking through the code trying to figure out what was wrong! Best of luck with your project(s).

  2. ZaldzBugz

    Hi Horace Ho, try to change this method below in your .H file

    + (id)sharedInstance; -> CHANGE TO -> +(SingletonClass*)sharedInstance;

    since + (SingletonClass*)sharedInstance is the one used in the implementation.

    -ZaldzBugz

    1. John Wordsworth

      Hi Adrian, glad that this helped. Yeah, it’s quite a jump going from Java to Objective-C – I’ve got a friend making the same transition now, and I can empathise with the learning curve! Thanks for the feedback.

    2. http://www.paquetesislamargarita.com/

      Pour la clope, un ami a surpris Pioline en train de s’en griller une près de la place des mousquetaires à Roland mais il était déjà retraité des courts à l’époque.En foot sinon, il me semble que dans le reportage « Les yeux dans les bleus » on voit furtivement Laurent Blanc fumer une tige dans le vestiaire après la demie contre la Croatie…

    3. http://www.staffmealsoftheworld.com/

      i wierzy odklejonemu od rzeczywistoÅ›ci czÅ‚owieczkowi, który nie ma bladego pojÄ™cia np. o gospodarce, od której tak naprawdÄ™ zależy los tych, którzy mu tak naiwnie ufajÄ…. A niech go sobie znowu wybiorÄ…. Ja sobie poradzÄ™, nie tu, to gdzie indziej. Oni – NIE.

  3. JK Scheinberg

    I’ve been searching around trying to understand singletons and this is by far the clearest explanation out there. Thanks for putting it up.

    1. John Wordsworth

      Thanks for the positive feedback. I keep meaning to put up some other snippets and tutorials, but it’s a struggle to find the time at the moment. Thanks for commenting.

  4. Nick

    Hello,

    I’m sorry for the trouble but I’m a bit confused about the final use lines that you provided:

    [sharedSingleton callAMethod];

    With the “callAMethod” part, do we create a method in the singleton and set the data to it or am I losing something? I’m very new to this so I apologize for not being able to get my point across well. Thanks in advance.

    Nick

    1. Nick

      Hello Again,

      I actually figured things out myself so no need to reply. This is what I ended up doing:

      I added the following under the *.h:

      NSString *general;

      With a method as follows:

      @property (nonatomic, copy) NSString *general;

      I then added the following under the *.m:

      @synthesize general;

      Then I was able to get and set the saved global information by adding the following under the other object:

      // set the value of the global “general” variable I created in the singleton class

      -(IBAction) setValue:(id)sender {
      [[GlobalsObject sharedInstance] setGeneral:@”test”];
      }

      // get the value of the global “general” variable that was set in the “setValue” action

      -(IBAction) setTextValue:(id)sender {
      barcode.text = [[GlobalsObject sharedInstance] general];
      }

      Thank you so much for posting this amazing tutorial. I am a brand new programmer and without this I would have never been able to complete my project. John Wordsworth, you are the man!

      Nick

  5. Pingback: Using Singletons for iPhone iOS 4 Global Variables « Nick Napier

  6. Van Du

    Hi,

    I think this is wrong:

    // Equally, we don’t want to generate multiple copies of the singleton.
    – (id)copyWithZone:(NSZone *)zone {
    return self;
    }

    it should be:

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

    However, will return self still works or do we need to call [self sharedInstance]?

    Thanks,

    1. John Wordsworth

      Hi Van Du,

      I could be wrong, but I’m pretty sure that copyWithZone should be an instance method (-) and not static (+). The method would normally be used to return a new instance that is a copy of the object that you call this method on. We simply return ‘self’ from the shared instance (you would call this [[SingletonObject sharedInstance] copyWithZone:zone]) as we don’t allow for more than one instance of the singleton to exist. See the NSCopying protocol for further details.

      Thanks for the comment, I’m still learning a lot of this as I go – so it’s always interesting to talk over certain points.

    1. John Wordsworth

      Hi Scott, the singleton will only be released when the app closes. Otherwise – the Singleton model is designed to kick around for the lifetime of your application. You could, of course, release elements that exist within your Singleton if you want to clear-up some memory and you’re storing large objects in your Singleton object!

  7. Claudio

    Hey John,

    Great stuff… I was wondering where I would initialize other objects within my singleton? Would you do it after the allocation of the shared instance or use “+initialize” ? Not sure what the “best practice” is…

    if (sharedInstance == nil) {
    sharedInstance = [[super allocWithZone:NULL] init];
    /* WOULD I DO IT HERE */
    }

    I’m still a n00bie with Objective C so I apologize if the question is stupid.

    Thanks,
    Claudio

    1. John Wordsworth

      Hi Claudio, no question is stupid when it comes to programming! Some things might be easier to grasp than others, but it’s actually all pretty complicated stuff when you take a step back and consider it.

      With regards to your question, you don’t really need to treat your Singleton any differently to any other object. I’ve updated the example above to include a template ‘init’ method where you might want to include your normal initialisation-type code for this object. The init method will only be called once, and that will be just before the first time you get your hands on the singleton (the first time you call [SingletonClass sharedInstance]).

      The only major caveat, is that you want to err away from init method that take parameters. As you’re not expected to care when / where your Singleton is initialised (it could be called anywhere in your code) it’s best to veer away from having any ‘initWith’ methods. It’s preferable to have a basic init method that sets up any required sub-objects and then you can configure those objects with additional instance methods on the singleton.

      Hope this helps, if you have any further problems, or this isn’t very clear – please don’t hesitate to drop me another message.

  8. Ajaxjava

    Can this [[SingletonClass alloc] init] still be called to create a new object? If yes, how to guarantee there is only one object in the memory?

    1. John Wordsworth

      Hi AjaxJava – thanks for dropping by and posting your comment. I hope my response helps to clear things up.

      As we have overridden allocWithZone: calling [SingletonClass alloc] will in turn call allocWithZone:, which simply returns the one singleton copy of this object (by calling the +sharedInstance method). If the static object does not exist already, then it will be created during the alloc call and a reference to it returned. Either way, you are still providing access to the one and only singleton object that exists in memory. Therefore, calling [[SingletonClass alloc] init] will return the one single copy of this class (creating it if necessary) and then call the init method on that instance. It is the overridden allocWithZone method that ensures that another copy of this object is never created in memory.

      If you are in a situation where you need to have a single copy of this class that is controlled and accessed by using [SingletonClass sharedInstance] but would also like to be able to create other copies of this class for other uses, then you can remove the methods allocWithZone:, copyWithZone, retain, retainCount, release, autorelease from the above code listing (basically, remove all methods except sharedInstance and init). This removes the restraint that only one copy of this class may ever exist, so only the one created by the sharedInstance method will be managed for you – you will have to memory manage all other copies of this class that you make yourself. Personally, i would err away from doing this, as I prefer to think that a class is either a Singleton or not (and not some strange hybrid), but the choice is yours!

  9. Pingback: Implementing a thread-safe Singleton in iOS | ampersand

  10. Dustin Pfannenstiel

    Am I missing something? How are you avoiding recursion hell…

    You call the sharedInstance. If it’s nil allocWithZone. Then in allocWithZone you return the sharedInstance, which requires calling sharedInstance. At this point it should still be nil so call allocWithZone…

    And repeat until insane.

    1. Dustin Pfannenstiel

      Never mind… problem existed between keyboard and chair. Call super’s allocWithZone.

  11. Jared

    Shouldn’t this line:

    static SingletonClass *sharedInstance = nil;

    Go before the @implementation tag? I don’t think you can declare any variables inside it.?

    1. John Wordsworth

      Hi Jared. Thanks for the comment.

      I have always declared my static variables just under the @implementation tag and never run into any problems before. I believe that the only variables you can declare within the @implementation section of a class are static variables (unless you use @implementation{ variables } construct – which is a relatively new feature I think). I’m fairly confident that declaring the static variable before or after the @implementation tag has exactly the same result and is simply down to style choice (I’ve seen both in libraries).

      1. car insurance quotes

        Subsequently, after spending many hours on the internet at last We’ve uncovered an individual that definitely does know what they are discussing many thanks a great deal wonderful post

      2. auto insurance

        leona:討論區有時決勝負的方式是「起底」,被起底之後便會消失。而我是那種不用真名寫就覺得麻煩的人。我也放過好多相上網,有朋友曾經警告,如果有人要 玩我就很危險,我認為自己的相本身就拍得醜而且怪,並且不介意便無問題——但那時還未看過網絡大典。現在看過之後,確是拗底了少少,但我想我還是會繼續這樣子寫。你寫文章也用真名,還談工作事,或許我們想法有相近之處。eric:從你的說法來看,似乎早期的網民對網絡的主體性比較在意?那麼給人的感覺是,網絡革命尚未成功,後代已經無所謂。是在流播速度極快的世代,我們反而要習慣特長的革命醞釀?三點:你還好吧?ä½ çš„blog前一陣子開始用書信體,感覺好像你被上左身咁。回來就好,儘情在blog裡大曬甜蜜吧。天氣冷,很難睡著,睡得也不舒服,一醒來又就發抖。睡過頭是在老家發生的,但在老家不能看書和寫東西。我現時主要是行「隔日入睡」機制,從這個角度看,失眠就少了很多。

      3. http://www.carinsurance.dynddns.us/

        Boa tarde!Tmb estou problemas, consigo baixar mas a extensão que aparece depois q baixo o filme é outra (rar), sendo que lá nas informações do filme tem dizendo AVI, q a única q não da problema. O que eu faço p mudar essa extensão??? Grata!!

        1. Latoya

          For those of you that didn't take the time to read Tr#o9aman&g3l;s super-de-duper triple post, let me break it down for you.First: imagine the sound of a TV test pattern.Second: dumb it down by about 50%Now you have a mental image (albeit slightly more intelligent) of what he/she/it wrote.

  12. Van Du Tran

    I think in the thread save section ther’es an error:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    + (SingletonClass *)sharedInstance {
    if (nil != sharedInstance) {
    return sharedInstance;
    }

    static dispatch_once_t pred; // Lock
    dispatch_once(&pred, ^{ // This code is called at most once per app
    singleton = [[SingletonClass alloc] init];
    });

    return singleton;
    }

    it should be

    sharedInstance = [[SingletonClass alloc] init];
    and return sharedInstance;

    Also, why is it in this case we do not call the initWithZone() but the regular init()?

    1. Van Du Tran

      Also, why in one case we have “sharedInstance = [[super alloc] initWithZone()] and in the other case we have “sharedInstance = [[SingletonClass alloc] init]

  13. Osni Oliveira

    Hi John,

    Thank you for your post, I found it to be very useful.
    Just a doubt here, your code for the allocWithZone overriding is:

    // We don’t want to allocate a new instance, so return the current one.
    + (id)allocWithZone:(NSZone*)zone {
    return [[self sharedInstance] retain];
    }

    If sharedInstance is a static variable not bout to the class implementation (proof of that is you can declare it inside or outside the @implementation section), why use self? And, most important yet, why call retain on sharedInstance, since you also override the retain method to do nothing and just return self?

  14. Pingback: Alex Westholm» Blog Archive » Reflections on one month of iOS development: Part II

  15. Oliver

    I don’t understand…
    In you rchapter “Making the creation of your singleton thread safe”, if I use the replace code, where is sharedInstance set ? It’s never initialised nor filled…

  16. Mike

    I’ve long been looking to store globals.
    I did LabView programming for 2 years, so the structure of programming isn’t new in itself, but still, this is a whole new world.

    I played around with the singleton and I think for what I want to do, it’s perfect. But I have a problem when using storyboard.
    I have a segue that switches from my 1st to my 2nd viewcontroller. If I put a button on the 2nd view and implement to update a label on the view with my string from the singleton, the label gets updated.
    If I put the assignment of my singleton string to the label under viewdidload, I always get null.

    What can I do here to solve this issue?

    Thanks.

    BTW, great post.

  17. Lee McLaughlin

    Hi,

    Thanks, very good tutorial.

    I think there is a slight typo/cop-over mistake here:

    + (SingletonClass *)sharedInstance {
    if (nil != sharedInstance) {
    return sharedInstance;
    }

    static dispatch_once_t pred; // Lock
    dispatch_once(&pred, ^{ // This code is called at most once per app
    sharedInstance = [[SingletonClass alloc] init];
    });

    return sharedInstance;
    }

    ^ have switched the ‘singleton’ variable to sharedInstance

    Thanks Again,

    Lee

  18. mrEmpty

    This code gives me a ton of errors, forbidden use of ‘super’ and ‘retain’ by ARC. Same with retain count etc. Everything from -(void)dealloc down throws errors. No idea why.

    1. Travis Beck

      If you’re using ARC you can just remove the following:

      // Your dealloc method will never be called, as the singleton survives for the duration of your app.
      // However, I like to include it so I know what memory I’m using (and incase, one day, I convert away from Singleton).
      -(void)dealloc
      {
      // I’m never called!
      [super dealloc];
      }

      // Once again – do nothing, as we don’t have a retain counter for this object.
      – (id)retain {
      return self;
      }

      // Replace the retain counter so we can never release this object.
      – (NSUInteger)retainCount {
      return NSUIntegerMax;
      }

      // This function is empty, as we don’t want to let the user release this object.
      – (oneway void)release {

      }

      //Do nothing, other than return the shared instance – as this is expected from autorelease.
      – (id)autorelease {
      return self;
      }

      AND CHANGE allocWithZone: to:

      // We don’t want to allocate a new instance, so return the current one.
      + (id)allocWithZone:(NSZone*)zone {
      return [self sharedInstance];
      }

  19. Chet

    The thread safe +sharedInstance method is wrong — you changed up the variable name.

    It should be:

    + (CurrentUser *)sharedInstance {
    if (nil != sharedInstance) {
    return sharedInstance;
    }

    static dispatch_once_t pred; // Lock
    dispatch_once(&pred, ^{ // This code is called at most once per app
    sharedInstance = [[CurrentUser alloc] init];
    });

    return sharedInstance;
    }

      1. cheap car insurance

        To me it looks like the methods and results of this paper are solid, and much more in line with common sense than previous, rather immature works that should not even have been published.Unfortunately, the migration figure in the addendum is (like almost always, these days) an atrocious cartoon of geographical migration misconceptions and misunderstandings.

      2. http://www./

        I was very ecstatic to find this site on bing.I wanted to say thanks to you with regard to this excellent read!! I undoubtedlyenjoyed every little bit of it and I’ve you bookmarked to check out new stuff you post.

      3. http://www./

        Kron Traube, J’ai un souvenir plus nuancé du post où Renato parlait du suicide. Il parlait de la nécessité, après un certain âge, de le faire apparaître comme accident. Je crois même qu’à ce propos, il citait Stendhal. Je ne suis pas toujours prêt à suivre l’opinion ordinaire, toutefois je dois avouer que je commence à croire en ceux qui vous accusent d’être un lecteur superficiel. C’est peut-être une allégation idiote, mais sous ce fil vous en donnez largement la preuve.

  20. Vincent Tanakas

    Hi, thanks for the article, but it seems that the code as posted results in a recursive deadlock. The sharedInstance method invokes the allocWithZone method which in turn invokes the sharedInstance method, before the sharedInstance pointer is assigned.

    When I run the code as listed (with the correction of renaming ‘singleton’ to ‘sharedInstance’, I deadlock.

    Commenting out the updated allocWithZone method will resolve this, but then it’s possible to bypass the lock if the user directly allocates a singleton using the alloc/init mechanism.

    1. Vincent Tanakas

      Looks like Dustin’s earlier post resolves this issue:
      + (SingletonClass *)sharedInstance {
      if (nil != sharedInstance) {
      return sharedInstance;
      }

      static dispatch_once_t pred; // Lock
      dispatch_once(&pred, ^{ // This code is called at most once per app
      singleton = [[super allocWithZone:NULL] init]; // Just calling [super alloc] would result in [self allocWithZone:NULL] getting called which would lead to a recursive block.
      });

      return singleton;
      }

  21. Pingback: Singleton Design Pattern « jamesdevnote

  22. Pingback: iOS4 – Static Classes | Russell Broadbent

  23. Ron L

    It is clear that we are eliminating multiple attempts to alloc the singleton. However, multiple calls to init seem possible and probable. After the singleton is allocated and initialized, does NSObject simply ignore future init calls?

    Example:

    SingletonClass *myObject=[[SingletonClass alloc]init];
    SingletonClass *moOtherAttempt=[[SingleClass alloc]init];

    the alloc call returns the sharedInstance. We then call init on the sharedInstance. Is this a problem?

    Thanks

  24. viktorvogh

    Thanks buddy. Worked like a charm.

    Had to disable Auto Reference Counting (ARC) in the project properties to make some methods legal. (iOS 6 SDK, Xcode 4.5.2)

    The other option is enabling ARC and removing the dealloc, retain, retainCount, release and autorelease methods.

  25. Thomas LEDUC

    Hello,

    Thanks a lot for this great example, but I have a little problem in thread safe singleton :
    static dispatch_once_t pred; // Lock
    dispatch_once(&pred, ^{ // This code is called at most once per app
    singleton = [[SingletonClass alloc] init];
    });

    return singleton;

    the var “singleton” is a mistake ? We must use “sharedInstance” isn’t it ?

  26. Pingback: iOS设计模式(02):单例模式 | 破船之家

  27. Jay Long

    Finally ! The whole package! Thanks for this!

    I know its using globals, but sometimes living in sin makes sense !

  28. Pingback: objc short call for singletonCopyQuery CopyQuery | Question & Answer Tool for your Technical Queries,CopyQuery, ejjuit, query, copyquery, copyquery.com, android doubt, ios question, sql query, sqlite query, nodejsquery, dns query, update query, insert

  29. Johnc381

    hi!,I really like your writing so so much! proportion we communicate more about your post on AOL? I need a specialist on this space to unravel my problem. Maybe that’s you! Looking ahead to see you. dcdbdedbddfd

  30. Pingback: Singleton Design Pattern In Objective C

  31. Robert Vaessen

    Hi John,

    Thanks for the great write up! I have a followup question.

    Let’s say that I have created a singleton class named MyClass using your template and have placed MyClass into a library. When other developers use it the most obvious code for them to write is [[MyClass alloc] init]. Your template takes care of the alloc method but what about init? What prevents the initialization from being performed every time that the singleton is obtained via a line of code such as [[MyClass alloc] init] ?

    Thanks,
    Robert

  32. Pingback: Creating a variable that will eventually hold a piece of data to be used by all methods | Yahl Answers

  33. miras

    i need to make the sharedInstance an audio player so i can initialise it only once and use it in different ViewControllers, but Xcode sends a warning (yellow) saying “incompatible pointer types……”
    how can i do so?

  34. Phan

    Thanks Day! One of the aspects I like about phahogropty is that in selecting a subject, framing and then shooting a photo you have time to reflect on the beauty you see through the lens. I too like Wordsworth but I LOVE Thoreau. He was an inspiration to me as a lad growing up in the country.Hugs,JerBear

Leave a Reply

Your email address will not be published. Required fields are marked *