On the Inter-webs, it’s very easy to find a piece of code that abuses singletons or a blog post that bitches why singletons are bad. Trust me, singletons are not bad. A singleton is a double edged sword. It’s up to you to use it the way it was intended to be used. In this post, I’ll talk about some often encountered problems where singletons are used in a wrong way and then provide you suggestions on how to overcome them.

While the examples I give here are iOS specific, Singleton is a design pattern. That means, you could apply this knowledge in pretty much any programming language.

Common (ab)use cases for a Singleton

You might find situations when you need to store the global state of the application somewhere. To store this state let’s create a singleton class called XYZManager.

The other common use case is you need a class that will probably be used inasmuch as every view of your application. So, let’s use a singleton.

Fortunately or unfortunately, using a singleton seems to solve both these problems, but will end you up in hot soup sometimes later during the project’s lifetime. Let’s see why.

Problem 1: Sharing global state

If you find yourself in a situation where your app has lots of global state and every class reads/writes to this state, you have made a terrible mistake in designing your app.

A rule of thumb for a good object-oriented design is to limit global state variables. Using a singleton solely to store your state variables is as bad as using global variables in your app. A singleton is not designed for that.

Of course, state variables cannot be completely removed in a software. Before you create such a variable, you should be doubly sure that the variable is truly global in your business domain.

Example

Let me give you an example. When you develop an app that talks to a web service, the only “state” variable I could think of is your access token. Using a Singleton to encapsulate calls to web service that remembers the access token is fine. But if you store the response strings from one method and use it in another method and then release it in yet another method, you are doing it wrong.

Let me quote a common example of this from iOS. You have a master-detail view. The details view can be reached only from the master view. The details view has an “Up/Down” segmented button that shows the previous/next content without having the user go back and forth. So let’s fetch the detailed content on a background thread and store it in a NSMutableArray in our singleton and whenever next button is tapped, increment the current index and update the UI. Neat and elegant, right? WRONG. It’s not the singleton’s responsibility to store data required by a few of the view controllers in your app. The problem with this method is, you cannot make an educated guess on when to release this NSMutableArray. A “clever” technique is to release it when the master view is unloaded. But then these “techniques” tightly couple the singleton with view controllers and affects reusability. Later on, if your business requirements change and you have to use the detailed view elsewhere, you will not be able to.

Another case is when you write a method in a singleton assuming that, so-and-so variable will have so-and-so values, when the control reaches there. If you have done this, you have tightly coupled your singleton with various other classes. This is something that’s very very hard to unit test.

Finally, because singletons don’t die and live till the end of the program, storing chunks of data like this results in a potential memory leak.

Problem 2: Managing state externally

A singleton’s state should be managed by one and only one class, self. If a view controller or another class changes the internal state variables of a singleton, you are doing it wrong. The getters of the singleton’s state variables can be public, but the setters should always be private. A good example from Cocoa is UIDevice class. It manages a wealth of state about the device, but nearly every state is marked readonly. When a state is changed, it often something that controls the behavior of the singleton.

If a singleton doesn’t manage any state, then you don’t actually need a singleton. What you need is a Façade object.

Problem 3: Dependent singletons

In your app, it’s “kinda” ok to have “too many” singletons, but ensure that they don’t talk to each other directly or indirectly. For example, you can have a FacebookManager, a TwitterManager and several other similar manager classes., but they shouldn’t communicate with each other. In other words, a singleton shouldn’t call methods in another singleton. For example, a method named, publishFeed in FacebookManager shouldn’t call publishTweet of TwitterManager. If you are doing this and cannot find a way out of this, merge them into one singleton. After all, they probably might be the “same” in your business domain. When you refactor considering this, you will find that your project with “too many” singletons actually has only one or two “real” singletons.

Another reason why you shouldn’t depend on a singleton method from another singleton is that, singletons are lazily loaded. You have no authoritative way to ascertain the order in which they are initialized (or the order in which they are torn down).

Problem 4: Delegates in a singleton

Asingleton is a global class. No one single class should “own” the delegate of a singleton. To notify state changes, observe them through KVO or NSNotificationCenter. PS: The very first version of MKStoreKit had this problem.

Mediator Pattern

If you still need two singletons to talk to each other, yet being independent, write a mediator class that handles this communication. Like in our previous case, if we have a FacebookManager and a TwitterManager and you want to publish an entry with one method call, write a mediator that “knows” how to publish to Facebook and how to publish to Twitter.

Ok, nuff said, When should I use singletons then?

Now that we know when not to use a singleton, let’s talk about some cases where you should be using them.

Singletons are good

Singletons are actually good, if you use them the right way. Every framework you have ever used, has a handful of singleton classes. iOS too have a few. UIDevice, UIApplication are some example. When you program for iOS, just look at how Apple uses them. A quick rule of thumb for your reference.

  1. Never change the state of a singleton from a class/method outside it.
  2. Never allow two or more singletons to talk to each other.
  3. Never write a method in a singleton that assumes/expects the state of a variable to be set to a particular value by another method. That’s methodB shouldn’t mandate that methodA should be called before it’s called.

Only a class that’s truly a singleton in your business domain will satisfy all these points. If any one of the above point sounds illogical to you, what you need is something else and not a singleton.

Thus, Singletons ain’t bad after all. If you are convinced, pick up my Xcode 4 singleton template.


Mugunth

Follow me on Twitter

  • Uli Kusterer

    One important point you forgot to mention about singletons (particularly in Objective-C, where we have class objects that can also used to implement singleton-ish functionality), is that singletons can be subclassed.

    So for example, if you want to standardize error message generation in your libraries and applications, you could create an ErrorManager singleton/class that all libraries use to generate the message for a string, then subclass it in each application so they transparently get error strings and solution suggestions without a need to change any code or even re-build libraries.

  • Mike Abdullah

    AppKit does disagree with you on changing the state of singletons though. e.g. NSFontManager and NSDocumentController. Arguably that could be that they shouldn’t be singletons in the first place; I can’t quite decide.

  • Bo

    What would you recommend for passing a NSMutableArray from the AppDelegate to a ViewController? Should I use a Singleton?

  • Nil

    What approach should be followed if I need to share an object between various classes and also need to update its state from those classes?