Fundamental iOS design patterns: SharedInstance (Singleton in Objective C)

Brief introduction

Singleton is one of the (if not THE) most commonly used/abused design pattern adopted in software development.
Basically it’s used to restrict the instantiation of a class to one object only that can be used safely across application architecture. Its implementation is pretty simple compared to other patterns and it’s very similar for the most of programming languages, but in Objective C it has a slightly different approach due to the lack of “normal constructor” that are instead replaced by alloc/init paradigm.

How it works in Objective C

In Objective C, we can speak more appropriately about the SharedInstance pattern rather than traditional Singleton.
This one is often used in Apple frameworks and differently from its twin brother, it does not explicitly forbid the instantiation of multiple class instances, but it simply provide a class method that will return a shared instance. During the first call to that method the instance will be allocated and the next calls will return the previously object created. So this is a sort of hybrid approach.
A common class that use this pattern is UIApplication which implements a sharedApplication method (which returns the current running application). Differently from Singleton which use getInstance(), in Objective C the corresponding method has not a fixed name but it should start with “shared” followed by the “type” of class (so for UIApplication is “sharedApplication” for MYAmazingManager will be “sharedManager“). Anyway there are several exceptions, for example NSFileManager has a “defaultManager” acting as a sharedInstance accessor that could be renamed “sharedManager“.

Pattern implementation

In my singleton implementations I simply call the accessor “sharedInstance“, in this way I can use a simple pre-compiler macro that automatically synthesize this methods for me.
Even implementation of this pattern may vary and personally I adopted one which is thread-safe and rely on CGD (Grand Central Dispatch), which is an affective C level API provided by Apple in order to handle concurrency.

The implementation of my sharedInstance method is the following (comments explain how it works):

+ (id)sharedInstance 
{
	// structure used to test whether the block has completed or not
	static dispatch_once_t p = 0;
	
	// initialize sharedObject as nil (first call only)
	__strong static id _sharedObject = nil;
	
	// executes a block object once and only once for the lifetime of an application
	dispatch_once(&p, ^{
		_sharedObject = [[self alloc] init];
	});
	
	// returns the same object each time
	return _sharedObject;
}

Pattern in action!

SharedInstance pattern is IMO the best way to share data across multiple viewControllers in iOS applications.
One practical example is a data manager to share Core Data stuff such managed object context. I realized my own manager so that I can access this objects anywhere with ease like:

[[MYDataManager sharedInstance] managedObjectContext];

Quick iOS tip: where is the right place to add and remove observers in UIViewControllers?

While I was debugging my iPhone app I noticed (thanks to my verbose logs) that certain methods were called multiple times… apparently like if they were in a loop. I lost several time trying to figure out why and then I realized that the problem was related to defining them in the wrong place! (technically not wrong at all, but definitely wrong in my app context).
I was adding listeners in viewDidLoad and removing them in viewDidUnload.
This is acceptable only if you have simple UIViewControllers that don’t work in composite controllers hierarchy (they are not contained in UINavigationController or UITabBarController).
viewDidLoad is called after the view controller’s view has been released, but in a controllers hierarchy this does not happen since controllers are retained by the container! This leads to multiple messages dispatched to registered observers, so if you have a UINavigationController containing a sequence of 5 viewController, handlers will be triggered 5 times (one for each controller).
The safely approach to add and remove listeners is instead in viewWillAppear: and viewWillDisappear:
Example:

- (void)viewWillAppear:(BOOL)animated
{
   [super viewWillAppear:animated];
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(foo:) name:UIKeyboardDidShowNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
   [super viewWillDisappear:animated];
   [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}

Quick iOS tip: invoke UITableView dataSource and delegate methods from a UITableViewCell

I faced a situation in my app where I wanted to access to UITableView datasource from a UITableViewCell. Specifically I implemented the same behavior of left green (+) button in the label contained in the cell, so if you click on it the editing action “UITableViewCellEditingStyleInsert” will be committed.
Since a cell is contained in a table we can easily access to it using self.superview (cast is required because superview returns a basic UIView *), then once we are sure that the table has a valid dataSource, we can manually invoke the selector tableView:commitEditingStyle:forRowAtIndexPath:. In order to pass the proper indexPath dynamically we rely on table method indexPathForCell: (we don’t know in which cell we are but table does!).
The complete code snippet is the following:

UITableView *table = (UITableView *)self.superview;
SEL sel = @selector(tableView:commitEditingStyle:forRowAtIndexPath:);
	
if ([table isKindOfClass:[UITableView class]] && [table.dataSource respondsToSelector:sel]) {
    [table.dataSource tableView:table 
             commitEditingStyle:UITableViewCellEditingStyleInsert 
              forRowAtIndexPath:[table indexPathForCell:self]];
}

Getting right UIImage and CGImage pixel size according to device display (retina or not)

I just fixed an issue related to the wrong display of an UIImageView in my (never ending WIP) app. The problem is that starting with iOS 4 and with the introduction of retina display in iPhone 4, the attribute “size” does not return the real pixel dimensions but points. So on a retina display device an image of 100×100 pixel will return a size of 200×200 (values are doubled). Theoretically there is an helpful attribute “scale” that should return a float value representing the adopted scale (2.0f for retina display, 1.0f for other).
Unfortunately, in my case it returns always 1, both for the iOS simulator than the real device (iPhone 4 with iOS 5), and my images are rendered incorrectly.
After digging on Google (which as usual points me to my beloved Stackoverflow), I gathered several helpful informations that helped me solving the problem and inspired a few helpful precompiler macros :)
The scale value, which is essential to implement retina display-aware software can be retrieved using:

[[UIScreen mainScreen] scale];

So, I realized the following macros:

// return true if the device has a retina display, false otherwise
#define IS_RETINA_DISPLAY() [[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2.0f

// return the scale value based on device's display (2 retina, 1 other)
#define DISPLAY_SCALE IS_RETINA_DISPLAY() ? 2.0f : 1.0f

// if the device has a retina display return the real scaled pixel size, otherwise the same size will be returned
#define PIXEL_SIZE(size) IS_RETINA_DISPLAY() ? CGSizeMake(size.width/2.0f, size.height/2.0f) : size

Then I used a little trick, to initialize an UIImage with the correct dimensions. Fundamentally I initialize an “helper image” first from which extract a CGImage in order to allocate a new UIImage using the initializer initWithCGImage:scale:orientation: (as scale I use the previous defined macro DISPLAY_SCALE).

UIImage *helperImage = [[UIImage alloc] initWithData:data];
UIImage *pic = [[UIImage alloc] initWithCGImage:helperImage.CGImage scale:DISPLAY_SCALE orientation:UIImageOrientationUp];

ALAssetsLibrary’s enumerateGroupsWithTypes:usingBlock:failureBlock: on iOS 4.3.4

I had 20 minutes of panic after installing iOS 4.3.4 on my iPhone 4. In fact, the app which I’m developing has stopped working due to a change in the ALAssetsLibrary api. The call to enumerateGroupsWithTypes:usingBlock:failureBlock:, which I use to retrieve all the media files on the device, did nothing (blocks didn’t get called and no error raised). After a couple of tests:

NSLog(@"is selector available? %@", 
[library respondsToSelector:@selector(enumerateGroupsWithTypes:usingBlock:failureBlock:)] ? @"y" : @"n");
	
NSLog(@"I'm on the main thread? %@", [NSThread isMainThread] ? @"y" : @"n");

I figured out that the fetching didn’t begins because it was invoked on a background thread (although this did works fine in iOS 4.3.3!).
In fact I’m using an NSOperationQueue with several NSOperations inside and one of them is the one invoking ALAssetsLibrary’s api.
So, to solve the problem I simply created a wrapper to the call using performSelectorOnMainThread:withObject:waitUntilDone:

UPDATE:
After a code refactoring and the upgrade to iOS 5, I finally realized that the problem is actually related to how ALAssetsLibrary works. read here!