Thursday, 11 October 2012

Objective C Singletons

I was writing my first app in Objective C using Apple's wonderous XCode IDE.  I had two view controllers launched from the nib to control a couple of views.  I needed to send data from one controller to another and had real difficulty.  The problem was that I couldn't use accessors to pass data, as I would prefer, because the viewcontroller objects weren't aware of each other.  After much reading, googling and 'youtube tutorialing' I settled on using a 'Singleton' object.  This great youtube tutorial by barrowclough was particularly helpful.

A Singleton is a custom class you create that can be accessed by any other objects.  It is declared in such a way that different objects instantiate this class they all end up with the same object. This means that the variables/attributes/properties of the Singleton can be get/set by any of those objects.
First thing was to create a new class (add new file to the project in XCode).  Here is the code for the Singleton custom class:

Singleton.h

#import <Foundation/Foundation.h>
@interface Singleton : NSObject {
    NSMutableArray *passedMutableArray;
}
@property NSMutableArray* passedMutableArray;
+ (Singleton *) sharedSingleton;
@end


Singleton.m

#import "Singleton.h"
@implementation Singleton
@synthesize passedMutableArray;

static Singleton *sharedSingleton = nil;
+ (Singleton *) sharedSingleton {
    @synchronized(self) {
        if (sharedSingleton == nil){
            sharedSingleton = [[self alloc] init];
        }
    }
    return sharedSingleton;
}
@end

Any variables that you would like to be 'globally' accessible are added to these files in the same way as I have demonstrated with passedMutableArray that appears on two lines in .h and one in .m.  You can add as many variables as you like - I have chosen to show only one (passedMutableArray) in my example.

Every class that will use the Singleton must: #import "Singleton.h" in its .h file and then create a singleton object (also known as instantiate an object of class Singleton) somewhere in its implementation with this line of code:

Singleton* mySingleton = [Singleton sharedSingleton];

To 'send' data via the Singleton its simply a case of setting the value of the Singleton property (passedMutableArray) in the first object in my example i.e.:
mySingleton.passedMutableArray = localMutableArray;


To 'receive' that data in the other object is similarly straightforward e.g.:

otherLocalMutableArray = mySingleton.passedMutableArray;


That's it - this is how I sent my mutable array from one view controller object to another.

For clarity, both local variables must be of the right type, in this case defined within the {} of the .h file of the two viewcontroller classes:

In first object's class: NSMutableArray *localMutableArray;
In other object's class: NSMutableArray *otherlocalMutableArray;

Also, both of the objects I refer to as sending and receiving data via the Singleton can do both sending and receiving, it's a two way thing.  Also, you are not limited to just two object accessing the Singleton as the properties are available to any classes that instantiates this Singleton.