iOS Best Practices – Singletons

Problem

Many examples found online utilize the AppDelegate instance for global storage/variables.  While this is a quick way of sharing data and methods between views and classes it can (and usually does) lead to several problems:

No control over global variables/storage

Each referencing class assumes direct control over this variable and won’t necessarily respect how another class is expecting to use it.  With a singleton, the data has been fully encapsulated and controlled in one place.

Repeated business logc

If there is any business logic on how this global storage is to be used it has to be repeated throughout the application.  While some may “encapsulate” this by using accessor methods the logic is in the wrong place.

Big Ball Of Mud

Very quickly, the AppDelegate class will become a big ball of mud and VERY difficult to maintain.  This is compounded over time as the app is revisioned and different developers add more and more code to the ball of mud.

Fixing the problem: Singleton

One way of fixing the “I need to put all my global variables in the AppDelegate” is to use Singletons.  A singleton is a design pattern (and implementation) ensuring that a given class exists with one and only one instance.  The developer can now store like variables and implementations together with the confidence that the same data will be retained throughout the application.  In fact, the AppDelegate is held in a singleton of your application ([UIApplication sharedApplication]).

The developer must also ensure to not repeat the same “big ball of mud” anti-pattern by simply moving all the code from the AppDelegate into one Singleton class.  The concept of single-purpose classes will be covered in a future post.

Implementation

The implementation is pretty straight-forward based on Apple’s Fundamentals and is made even simpler using ARC in iOS 5.  The trick is ensuring all code that references this class is using the exact same instance.

Steps/tips for a Singleton in Objective-C:

1. Implement a “shared manager” static method to dynamically create and retrieve the same instance each time.

static SingletonSample *sharedObject;
+ (SingletonSample*)sharedInstance
{
if (sharedObject == nil) {
sharedObject = [[super allocWithZone:NULL] init];
}
return sharedObject;
}

2. Leverage public shared methods as a convenience factor to encourage use of the singleton.

+(NSString *) getSomeData {
    // Ensure we are using the shared instance
    SingletonSample *shared = [SingletonSample sharedInstance];
    return shared.someData;
}

3. Create and use instance variables and methods as you normally would

@interface SingletonSample : NSObject {
    // Instance variables:
    //   - Declare as usual.  The alloc/sharedIntance.
    NSString *someData;
}

// Properties as usual
@property (nonatomic, retain) NSString *someData;

4. Use the class via the shared methods and/or instance

- (IBAction)singletonTouched:(id)sender {
    // Using the convenience method simplifies the code even more
    self.singletonLabel.text = [SingletonSample getSomeData];
}

The full source code with sample application is available here: https://github.com/JAgostoni/iOS-Best-Practices/tree/master/BigBallOfMud

About these ads

5 thoughts on “iOS Best Practices – Singletons

  1. One more addition: You need to make it thread-safe too;
    So if I want to create a session class which is singleton in nature, then my code will look like

    +(SessionBO*) sharedInstance{
    @synchronized(self){

    if (! sharedObject)
    {
    sharedObject = [[SessionBO alloc] init];
    }
    return sharedObject;
    }//end synchronized block
    }

  2. note that @synchronized will only make the creation thread safe. further access to the singleton will NOT be thread safe.

    you can also use dispatch_once for this:

    + (SingletonSample*)sharedInstance {
    static ILTestSingleton* instance;
    static dispatch_once_t onceToken = 0;

    dispatch_once(&onceToken, ^{
    instance = [[SingletonSample alloc] init];
    });

    return instance;
    }

  3. Pingback: Class Cluster as a Singleton? | BlogoSfera

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s