They say one is the loneliest number. But sometimes it is important to have only one instance for a class. In these situations, being singleton is great! What is a singleton you ask? (Thanks for asking. I was kind of lonely here at my computer before you came along. Can we be friends?) Well singleton pattern is one of a number of iOS design patterns. This particular pattern involves creating a single class that is responsible for creating an object and making sure that only one instance of said object is created across the system*. You can kind of think of a singleton as a “property” for an entire project. Let’s go a little more into depth about what a singleton pattern is, how we use it, and its pros and cons.
Step 1: Know that you are unique and special and no one can replace you!
As mentioned previously, a singleton design pattern ensures that only one instance of an object exists for a given class. This class also provides a global access point to that instance, which allows us to access data from the singleton throughout different classes. I noted before that we can think of singletons as sort of properties for our class because the scope of our singleton extends through all the classes in our workspace. Meaning we can add, remove, edit etc. the same data throughout our program and within numerous View Controllers. Neat, huh?
The first instance of a singleton class is commonly created with lazy initialization, a technique used to delay computationally or memory-intensive operations until they are absolutely necessary – particularly useful for putting of an objects initialization way in order to improve responsiveness or memory use for other processes). I digress. Back to singletons: Apple actually uses singletons in their built-in classes. Some examples are [
[UIScreen mainScreen] and
[NSFileManager defaultManager].These class methods return a singleton object (looks like this stuff is more useful than you thought, huh?).
Step 2: Know that you are a great option! (…in certain situations)
There are a few advantages to the singleton life, the first, which we mentioned previously, is accessibility. Creating a singleton will allow your data to persist while your app is open through different view controllers with ease. Another advantage is the intuitiveness of the pattern. Sometimes it just makes sense in the architecture of your project to only have one class floating around. A prime example of this would be the creation of a singleton for logging. There is no need to have multiple logger classes, unless you want to write several log files at once.
Making Yourself Available
Creating a singleton is quite simple and can be done with just a few code snippets so lets implement a simple file logger, shall we?
Above, we have created our new
Logger class. We also created a class method,
sharedLogger, to access the singleton object. Anytime we want to add, delete, or edit information from our singleton, we need to do so by calling this
sharedLogger class method. The definition of this method is as follows:
In order to access the singleton object, first we declare a static variable
_sharedInstance (line 16). This instance variable holds a reference to the singleton object and the use of the static modifier ensures that the function “remembers” its value across all invocations. Next we create our
dispatch_once_t predicate, which acts like a one way ticket and use our one way ticket when we invoke
dispatch_once, a Grand Central Dispatch function. The GCD ensures will run one time and one time only (lines 18 – 23).This is very important since we only want to initialize one instance of the
Logger class. The last thing we do is return our
, which allows us to access the
Logger instance. And that’s it! Ta da! We have created a singleton object that will persist throughout our project.
Step 3: Watch out for tight coupling!
You take the good, you take the bad…There are indeed disadvantages to singletons:
A marker of a good object-oriented program is that that it is abstracted enough so that each object can stand up on its own. Coupling, in general is, is the degree of interdependence two routines or modules are connected. Tight coupling, as you may be able to infer, is a strong dependence between two or more modules. This, by many programmers, is considered bad practice in object-oriented programming. Lets look at an example to better understand why: You havve created an iOS app that uses a networking component accessed through the
UIApplication singleton. Because you’re an amazing programmer, your app is a huge success so you decided that you want to make it into an OS X application. But the
UIApplication class is not available on OS X because UIKit is specific to OS X. Crap. So using a singleton in this situation results in poor reusability, and we would have to refactor our iOS app quite a bit before being able to release it on OS X (Darn! The world is going to have to wait oh so long before we can release an OS X version of our Cat Videos On Demand app).
A second marker of a good object-oriented program is that objects should only be able to interact with other objects if they have references to each other and should not be able to interact with each other if there are not. Thus, if we instantiate two objects, A and B, and never pass a reference from A to B, they should in no circumstance be able to interact each other. But, if we throw a singleton into the mix, these two classes, which have no permission to interact with each other can actually change each others states. How? Well,if object A has gained access to modifying singleton C, then object B is instantiated and also starts modifying singleton C, then both A and B can affect each other through singleton C. Spooky!
Step 4: Be content with what you are, the good, the bad, and the ugly
As we have seen, singletons are very powerful, but can also have disastrous consequences and should be used with caution. Many programmers consider singleton patterns anti-patterns because of the potential consequences of using them and go so far as to say that singletons should not be used for the reasons noted above. There are numerous articles that shun singletons, this one by Misko Hevery being particularly interesting! But the moral of this story is watch out where you put your singletons because improper usage could be bad news bears. If you feel so inclined to use a singleton in your code, think about whether or not there is an alternate method to achieving the goal you want to achieve before you do, and try use singletons sparingly.
* For the sticklers out there, it is important to note that there are actually two different “types” of singletons: functional singletons and true singletons. A functional singleton is instantiated once and is reused in several places by calling its getter, but it is programmatically possible to instantiate a functional singleton more than once (Why, god, whhyyy?!) . A true singleton is a class that, no matter what, always returns the same instance of itself .
** many thanks to this article by Bart Jacobs, which pretty much taught me all of the above.