While I was at Apple’s Cocoa Camp over summer, one of the speakers talked rather passionately about the proper, thread-safe way to implement a singleton in iOS, which I thought deserves more attention than it currently does on the Web.
The Common Naive Way
According to the first result on my Google search, a singleton should be implemented as follows:
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;
}
Although this method is quick and easy, it is not thread-safe and the object constructor might be called multiple times if several threads access the method concurrently. We need a way to lock the constructor and insist that it be executed at most once. This is where Grand Central Dispatch comes in.
The Troublesome Thread-safe Way
GCD provides a neat API that makes concurrency programming in Cocoa convenient. To implement a thread-safe singleton in Cocoa, all you need to do is the following:
static MyObject *singleton = nil;
+(MyObject *) sharedInstance {
NSLog (@"sharedInstance called.");
if (nil != singleton) return singleton;
static dispatch_once_t pred; // lock
dispatch_once(&pred, ^{ // this code is at most once
singleton = [[MyObject alloc] init];
});
return singleton;
}
Let’s look at the code in detail. First, notice that the first few lines are the same: we have a static variable for our singleton, and we check whether it is nil whenever we access sharedInstance. If singleton is nil, allocate and initialize it; otherwise, return it.
The real difference is where we use the dispatch_* types and functions. You may think of dispatch_once_t as a type of lock that dispatch_once() uses to ensure that the code is executed at most once. Here, we wrap up whatever code we wish to be executed during the initialization of our singleton in a block. We then pass the block as an argument to dispatch_once. (Here’s a pretty good tutorial on blocks.)
This implementation ensures that singleton is never executed more than once even when multiple threads access sharedInstance concurrently:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0U);
dispatch_apply(10, queue, ^(size_t i){
[MyObject sharedInstance];
});
The above code results in the following output:
2011-09-05 10:12:05.961 SingletonTest[1602:10c03] sharedInstance called. 2011-09-05 10:12:05.961 SingletonTest[1602:12603] sharedInstance called. 2011-09-05 10:12:05.961 SingletonTest[1602:ef03] sharedInstance called. 2011-09-05 10:12:05.961 SingletonTest[1602:12703] sharedInstance called. 2011-09-05 10:12:05.966 SingletonTest[1602:10c03] init called. 2011-09-05 10:12:05.966 SingletonTest[1602:ef03] sharedInstance called. 2011-09-05 10:12:05.966 SingletonTest[1602:10c03] sharedInstance called. 2011-09-05 10:12:05.966 SingletonTest[1602:12703] sharedInstance called. 2011-09-05 10:12:05.966 SingletonTest[1602:12603] sharedInstance called. 2011-09-05 10:12:05.969 SingletonTest[1602:10c03] sharedInstance called. 2011-09-05 10:12:05.969 SingletonTest[1602:ef03] sharedInstance called.
7 Responses to “Implementing a Singleton in iOS”
Trackbacks/Pingbacks
- Implementing a Singleton in Objective-C / iOS | Dr John Wordsworth - [...] only ever called once, even if it’s called concurrently on different threads then check out Jiunn Haur’s great blog ...

A great post on something that I hadn’t thought about since I first wrote my blog post back in April of last year. Back then, I was pretty new to Objective-C development and making it thread-safe wasn’t something that I had considered (especially as GCD wasn’t available in iOS at the time).
I’ve updated my blog post with a link to yours. For the purpose of improving my article, would you mind if I used your sharedInstance method in my post? I would of course attribute it back to you and point to your post for the explanation!
Lastly, wow – I hadn’t realised that my blog came up as the first result in Google. I blogged about it during my iOS coding learning experience, mostly for my own use as a reference!
Hey John,
Thank you for your comment! Sure, you may use my code on your article as long as you link it back to me.
Hi Jiunn, I have updated my blog post with a section that uses your sharedInstance method above. I’ve included a link back to your blog and a link back to this post. Hope that’s ok and thanks for letting me use your snipped!
Another approach is to simply overwrite the
+(void)initializemethod in your singleton class, which apparently runs once just before a class receive its first message. And it’s thread-safe too!Reference: stackoverflow at http://bit.ly/9gE7g
Hey Rod! Thanks for your comment. This is a creative idea, and it probably creates the singleton when the program is first loaded. Using my method creates the singleton the first time you call
sharedInstance. I guess it is up to the programmer to decide which way is better: to be eager or to be lazy.From the docs: “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.)”
I think you’re overcomplicating the matter. You can use an ‘@synchronized’ block to achieve the same effect in a much more readable way. Basically take the original ‘sharedInstance’ implementation, put an ‘@synchronized’ block around the whole thing, and you’re done.