Skip to main content

The Singleton Pattern

The Singleton Pattern

Objective-C: Singletons

A Singleton is a special kind of class where only one instance of the class exists for the current process. Singletons can be an easy way to share data and common methods across your entire app. 


Note: Apple uses this approach a lot. For example:

[NSUserDefaults standardUserDefaults][UIApplication sharedApplication][UIScreen mainScreen][NSFileManager defaultManager] all return a Singleton object.


How to Use the Singleton Pattern

Take a look at the diagram below:


@interface LibraryAPI : NSObject
+ (LibraryAPI*)sharedInstance;
@end

+ (LibraryAPI*)sharedInstance
{
    // 1
    static LibraryAPI *_sharedInstance = nil;
    // 2
    static dispatch_once_t oncePredicate;
    // 3
    dispatch_once(&oncePredicate, ^{
        _sharedInstance = [[LibraryAPI alloc] init];
    });
    return _sharedInstance;
}

There’s a lot going on in this short method:
  1. Declare a static variable to hold the instance of your class, ensuring it’s available globally inside your class.
  2. Declare the static variable dispatch_once_t which ensures that the initialization code executes only once.
  3. Use Grand Central Dispatch (GCD) to execute a block which initializes an instance of LibraryAPI. This is the essence of the Singleton design pattern: the initializer is never called again once the class has been instantiated.
The next time you call sharedInstance, the code inside the dispatch_once block won’t be executed (since it’s already executed once) and you receive a reference to the previously created instance of LibraryAPI.

@synchronized vs dispatch_once


http://blog.bjhomer.com/2011/09/synchronized-vs-dispatchonce.html [Reference link]

It looks like dispatch_once is about 2x faster than @synchronized
Each test accessed the singleton object 10 million times. I ran both single-threaded tests and multi-threaded tests. Here were the results:

Single threaded results
-----------------------
  @synchronized: 3.3829 seconds
  dispatch_once: 0.9891 seconds

Multi threaded results
----------------------
  @synchronized: 33.5171 seconds
  dispatch_once: 1.6648 seconds

dispatch_once() is absolutely synchronous. Not all GCD methods do things asynchronously (case in point, dispatch_sync() is synchronous). The use of dispatch_once() replaces the following idiom:
+ (MyClass *)sharedInstance {
    static MyClass *sharedInstance;
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[MyClass alloc] init];
        }
    }
    return sharedInstance;
}
The benefit of dispatch_once() over this is that it's faster. It's also semantically cleaner, because it also protects you from multiple threads doing alloc init of your sharedInstance--if they all try at the same exact time. It won't allow two instances to be created. The entire idea of dispatch_once()is "perform something once and only once", which is precisely what we're doing.

Comments

Popular posts from this blog

What's the difference between enum, struct and class?

Enums An enum is considered as a structured data type that can be modified without needing to change say a String or Int multiple times within your code, for example the below shows how easy it would be to change something by accident and forget to change it somewhere else. let myString = "test" if myString == "ttest" { // Doesn't execute because "ttest" is the value assigned to "myString" } With a enum we can avoid this and never have to worry about changing the same thing more than once enum MyEnum : String { case Test = "test" } let enumValue = MyEnum . Test if enumValue == MyEnum . Test { // Will execute because we can reassign the value of "MyEnum.Test" unless we do so within "MyEnum" } Structs I'm not sure how much you know about the MVC pattern but in Swift this is a common practise, before I explain how structs are useful I'll...

SQLite 3 Procedure & Functions

SQLite 3 Procedure & Functions iOS - SQLite Database SQLite can be used in iOS for handling data. It uses sqlite queries, which makes it easier for those who know SQL. Steps Involved Step 1.  Create a simple  View based application . Step 2.  Select your project file, then select targets and then add  libsqlite3.dylib  library in choose frameworks. Step 3.  Create a new file by selecting File-> New -> File... -> select  Objective C class  and click next. Step 4.  Name the class as  DBManager  with  "sub class of"  as NSObject. Step 5.  Select create. Step 6.  Update  DBManager.h  as follows − SQLite 3 Functions Preview sqlite3_open : This function is used to create and open a database file. It accepts two parameters, where the first one is the database file name, and the second a handler to the database. If the file does n...

Understanding of Size Classes?

Size Classes are an abstraction of how a device should be categorized depending on its screen dimensions. Apple defined two categorizations for both vertical and horizontal sizes called “Regular” and “Compact”. The former specifies a big space, while the latter specifies a small” space. How big or small exactly? Here, “big” and “small” are not intended to be measured in inches. iOS Size Classes Apple has introduced many devices like iPhone, iPad with different screen sizes and resolution. Also after iOS 8 apple has supported multitasking in iPad. So for the developers to develop a common or single UI for all the devices apple has introduced the concept of an adaptive layout by combining auto layout and size classes. What is adaptive layout: The adaptive layout is a method of building the apps based on the size and characteristics of the container instead of a targeting a particular device. We can create a single layout to work on all...