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

iOS Best Practices – Introduction

As my work gets more and more into mobile development (primarily iOS) I find our typical adoption to best practices (in .NET and Java, for example) not as strong. Whatever the reason, these practices are just as important on mobile platforms as they are on web and desktop platforms. The fact that a mobile device has more constrained resources or has fewer technology choices should have no impact on proper coding and design practices.

There are several books (Apple and otherwise) that I can recommend that cover basic coding conventions and UI design guidelines so i’ll try not to re-hash much of that here. As I encounter references and resources such as these I will link to them in a resources section.

The following series of posts is meant to document iOS design and development best practices as I have encountered them both in practice and as I have found them researching across the Internet. I encourage anyone following along to not only share the practices but to critique and contribute as well.

This introductory post will serve to index all the posted best practices:
1. Avoiding the big ball of mud (part 1) – Singletons – http://wp.me/p15S8e-3d