Creating singletons using dispatch_once

Love them or loathe them, sometimes you need to have a singleton. In fact every iOS and Mac OS application has at least one, UIApplication or NSApplication.

So what is a singleton? Wikipedia defines it as:

In software engineering, the singleton pattern is a design pattern used to implement the mathematical concept of a singleton, by restricting the instantiation of a class to one object.

Or as I would put it:

A singleton is a class, where only one instance of it can instantiated.

Although this is the actual definition of a singleton, this isn’t always the case in the world of Foundation. NSFileManager and NSNotificationCenter for example, are usually accessed through their class methods defaultManager and defaultCenter respectively. Although not strictly a singleton, these class methods return a shared instance of that class that developers can then access throughout their code. It is this approach that we will be looking at in this post.

There has always been a debate on the best way to implement the singleton pattern using Objective-C, and developers (including Apple) seem to have been changing their minds every couple of years. When Apple introduced Grand Central Dispatch (GCD) (in Mac OS 10.6 and iOS 4.0) they introduced a function that is perfect for implementing the singleton pattern.

This function is dispatch_once:

void dispatch_once(
    dispatch_once_t *predicate,
    dispatch_block_t block);

This function takes a predicate (which is a long, that in reality acts as a BOOL) that the dispatch_once function uses to check if the block has already been dispatched. It also takes the block that you wish to only be dispatched once for the lifetime of the application, for us this is the instantiation of our shared instance.

Not only does dispatch_once mean that your code will only ever get run once, it is also thread safe, which means you don’t have to bother with using anything like @synchronized to stop things getting out of sync when using multiple threads and/or queues.

This is verified by Apple’s GCD Documentation:

If called simultaneously from multiple threads, this function waits synchronously until the block has completed.

So how would you use this in practise?

Well let’s say you have a AccountManager class, and you want to access a shared instance of this class throughout your application. You can simply implement a class method like the one below:

+ (AccountManager *)sharedManager {
    static AccountManager *sharedAccountManagerInstance = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
      sharedAccountManagerInstance = [[self alloc] init];
    });
    return sharedAccountManagerInstance;
}

This means whenever you want access this shared instance all you need to do is:

AccountManager *accountManager = [AccountManager sharedManager];

And that’s all there is to it, you now have a shared instance that you can access throughout your application, which will only be created once.

This approach has many advantages:

  1. It is thread safe
  2. It will keep the static analyser happy
  3. It is compatible with Automatic Reference Counting (ARC)
  4. It only requires a small amount of code

The only disadvantage with this approach is that it will still allow a non shared instance to be created:

AccountManager *accountManager = [[AccountManager alloc] init];

Sometimes you will actually want this behaviour, but it is something you need to be aware of when you really only want one instance of a class to ever be instantiated.

WWDC 2011 Keynote Predictions

I predict that the keynote will about Mac OS Lion, iOS 5 and iCould … OK we already know that, so here is what I think that really means.

iCloud

I think that iCloud will give users the ability to stream any of their iTunes purchased music tracks and videos to an iOS/Mac OS device, for a small subscription fee ($25-$50 per year). I don’t think they will do what Google and Amazon are currently doing, whereby they allow users to upload their own music regardless of where the files have come from (e.g. burned from a CD), and then stream this to users devices.

I also think that iCloud will incorporate the MobileMe service, and what would make things very interesting is if Apple do something smart with iDisk. If Apple makes iDisk available to every iOS application via a nice and simple API, it would solve two major problems.

At the moment a lot of iOS applications use Dropbox for this, but it doesn’t have to be this way, and Apple will probably want a piece of this pie.

Mac OS Lion

I don’t think we (developers) will see anything new from Lion in this Keynote (other than anything iCloud related), but they are likely to go over the previously unannounced features such as Version and AirDrop. I think the GM will be given to developers at WWDC, and we will be given a release date … I think the end of July.

iOS 5

Notifications, Notifications, Notifications. I think Apple have to deal with how applications show notifications. At the moment they force the user to deal with them there and then … which may have been the simplest option to implement in iOS 1, but every other mobile OS has a better solution in comparison to iOS.

I think in tandem with the new notification system the springboard will get a small update to accommodate them. I’m not expecting anything major but support for widgets would be nice.

Over the air updates … I think this may finally happen. For me having to plug my iPhone into my Mac for it to upgrade the OS isn’t really an issue, it’s the syncing of apps and music (which I do regularly) that is the major issue. If they allow me to sync over WiFi (or something clever with iCloud) then I will be extremely happy with this as an iOS update.

What there won’t be

There will be no iPhone 5 (or iPhone 4S or whatever it is called) shown at WWDC, neither will there be any iPad hardware updates. I think the only hardware that we might see unveiled is a Thunderbolt MacBook Air, or a refresh of the Time Capsules to do something clever with iCloud … it does have a hard drive after all.

Jump in at the Deep End

A personal post/announcement that I thought I would share:

Today is the last day (for a while at least), that I am a full time employee of someone else’s company, earning a guaranteed salary every month being an iOS developer. At 5:30pm (maybe a bit earlier … it is Friday after all) I will become an indie developer, and I will start working full time on a few applications that I have had in mind for quite a while. As much as I tried, I couldn’t dedicate enough time to these projects while being a full time employee of another company, so I have decided to “Jump in at the Deep End” and start working on these projects full time. It’s a challange and a risk, but one that I am relishing, so hopefully I will make it out the other side in one piece.

If anyone has any advice about running a company (I’m in the UK), or on being a Indie Software Developer than feel free to share it in the comments section, or @ reply me on Twitter (@ObjColumnist).

Performing a block of code on a given thread

This post has been a long time coming, mainly because I cannot claim that I done any of the work to make it possible, for that I have to thank the Big Nerd Ranch and Landon Fuller. Nevertheless, I have found the following category so useful that I thought I would do a post on it anyway.

When I first started using blocks, I thought “I have this block of code, can’t I just run it on a given thread?”. The answer is (thankfully) yes, but Apple don’t supply a simple API to do this in Mac OS or iOS. The category below solves this issue:

@implementation NSThread (MCSMNSThreadCategory)

+ (void)MCSM_performBlockOnMainThread:(void (^)())block {
    [[NSThread mainThread] MCSM_performBlock:block];
}

+ (void)MCSM_performBlockInBackground:(void (^)())block {
    [NSThread performSelectorInBackground:@selector(MCSM_runBlock:)
                               withObject:[[block copy] autorelease]];
}

+ (void)MCSM_runBlock:(void (^)())block {
    block();
}

- (void)MCSM_performBlock:(void (^)())block {
    if ([[NSThread currentThread] isEqual:self]) {
        block();
    } else {
        [self MCSM_performBlock:block waitUntilDone:NO];
    }
}

- (void)MCSM_performBlock:(void (^)())block waitUntilDone:(BOOL)wait {

    [NSThread performSelector:@selector(MCSM_runBlock:)
                     onThread:self
                   withObject:[[block copy] autorelease]
                waitUntilDone:wait];
}

- (void)MCSM_performBlock:(void (^)())block afterDelay:(NSTimeInterval)delay {

    [self performSelector:@selector(MCSM_performBlock:)
               withObject:[[block copy] autorelease]
               afterDelay:delay];
}

@end

This category adds a set of (simple) methods to the NSThread class, that allows you to run a block on any thread that you have a reference to. (You may notice that the Big Nerd Ranch prefix their category methods with BNR and I use MCSM, this is due to Objective-C not supporting namespaces).

For more information on blocks, see Apple’s Blocks Programming Topics documentation.

Alongside blocks Apple introduced Grand Central Dispatch (GCD) in Mac OS 10.6, and I suggest that anyone implementing processor intensive tasks that require code to be executed off of the main thread should try and implement their code using GCD. That being said there are situations (predominantly due to the use of legacy APIs/libraries) whereby the use of a dedicated thread is still required.

Say you have a network thread (networkThread), and on this thread is network socket which is maintaining a persistent connection to a server, and a parser for the data that is received on that socket. (There is a common mistake I see, whereby programmers do the network I/O off of the main thread but still parse the data on the main thread, thus locking up the application’s UI when the data is being parsed).

Normally the data you want to send over the network originates from something that has been triggered from the application’s UI, and therefore the main thread. You then need to get this data onto the network thread so it can be sent.

Say you wanted to send a person’s first name (firstName), last name (lastName) and company name (companyName) over the network.

Ideally you would have a method that looked something like:

- (void)sendFirstName:(NSString *)firstName
             lastName:(NSString *)lastName
          companyName:(NSString *)companyName;

This method would convert the data into a format that can be sent over the network (e.g. XML, JSON etc), and queue it on the socket for sending.

The issue is if two threads try to use the same socket at the same time your application will crash, so this method can only ever be called from the networkThread. This is also relevant for other non-thread safe APIs.

So for this example we will rename it to:

- (void)onNetworkThreadSendFirstName:(NSString *)firstName
                            lastName:(NSString *)lastName
                         companyName:(NSString *)companyName;

and keep the original method for use on the main thread.

So how do you call a method on another thread?

Well you can’t directly, you have to use:

- (void)performSelector:(SEL)selector
               onThread:(NSThread *)thread
             withObject:(id)object
          waitUntilDone:(BOOL)wait;

The only problem with this is that the selector you call can only take one argument (using the withObject: parameter), and in this example we want to pass 3.

So what we need to do is put all of the arguments into one object. You could do this using an array (you would need a fixed amount of arguments to do this), a custom object (overkill if it is only going to be used as an argument to a method) or a dictionary which is what I will be using.

- (void)onNetworkThreadSendArguments:(NSDictionary *)arguments;

This means that you would end up with an implementation such as the following:

- (void)sendFirstName:(NSString *)firstName
             lastName:(NSString *)lastName
          companyName:(NSString *)companyName {

    NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:
                                                firstName, @"firstName",
                                                lastName, @"lastName",
                                                companyName, @"companyName", nil];

    [self
        performSelector:@selector(onNetworkThreadSendArguments:)
               onThread:networkThread
             withObject:arguments
          waitUntilDone:NO];
}

- (void)onNetworkThreadSendArguments:(NSDictionary *)arguments {

    NSString *firstName = [arguments objectForKey:@"firstName"];
    NSString *lastName = [arguments objectForKey:@"lastName"];
    NSString *companyName = [arguments objectForKey:@"companyName"];

    [self
        onNetworkThreadSendFirstName:firstName
                            lastName:lastName
                         companyName:companyName];
}

- (void)onNetworkThreadSendFirstName:(NSString *)firstName
                            lastName:(NSString *)lastName
                         companyName:(NSString *)companyName {
    // format and send data
}

So before 10.6 this technique would be common practise, but it means you have to write extra methods to pack and unpack arguments for cross thread calls.

Thankfully we can get this down to 1 method call using our block category on NSThread:

- (void)sendFirstName:(NSString *)firstName
             lastName:(NSString *)lastName
          companyName:(NSString *)companyName {

    [networkThread MCSM_performBlock:^{
        // format and send data
    }];
}

As the block of code is always executed on the network thread, this method can be called from any thread. As you can see blocks can be very useful even when used without Grand Central Dispatch.

This category is available on github here.

Come see what 2011 will be the year of. - Predictions

Apple’s first keynote of year is nearly upon us, but what will it bring?

Lion preview

Apple caught everyone by surprise last week by making the Mac OS 10.7 Lion preview available to developers. I expect Apple will go over some of the previously unannounced features such as Versions and AirDrop (I think everything has been leaked now though … naughty developers!!!).

iPad 2.0

I’m firmly under the impression that the iPad 2 will be a minor update that will simply keep it ahead of the competition. I think a front facing “FaceTime HD” camera will be included alongside a faster processor and more RAM. I don’t think it will get an SD card slot and I don’t think it will get a retina display … although I would like to see that.

MobileMe

MobileMe can no longer be purchased, but Apple have already stated that their new data center will be used for it. This is the strongest indication that it is simply just changing form. I think there will be a free version with Dropbox type functionality, so you can easily share files between your iOS devices. Other than that I’m not sure what they will add.

Something to do with the BBC?

The BBC are hosting an event at the same time as Apple’s keynote, so I imagine there is some link between them.

I think it will be one of 2 things:

iOS 4.3

iOS 4.3 will be made available tomorrow, but I don’t think there will be any surprise features.

iOS 5.0

One thing that I would like to see is the beta of iOS 5.0. I think iOS 5.0 really needs to clean up how notifications work, I suggest they copy webOS’s very clean and simple implementation. In addition to that I would like some sought of synergy between my iPad and iPhone (through MobileMe?) whereby I can do things such as replying to text messages on my iPad. They may even open up the Apple TV in iOS 5.0 … that would make things interesting.

Mac AppStore Launch

The Mac AppStore (MAS) is coming to a Mac near you on the 6th January 2011, but is it going to change the software landscape on the Mac forever?

Number of applications:

If there is one thing that we can be sure of, it is that the number of applications available for Mac OS will increase due to the introduction of the MAS. There will be iOS developers jumping on board (who are in for a shock when they see NSTableView), and also developers coming “Back to the Mac” after spending some time doing iOS development.

Quality of applications:

Quality and Quantity are two very different things. Just because the quantity of applications increases, that doesn’t mean that the number of high quality applications (that we have come to expect on the Mac) will increase accordingly. I (unfortunately) think that there will be a lot of substandard applications released for the Mac, simply because of the MAS making distribution easier. I do however think that there will be a few gems uncovered because of it.

Price of applications:

When the Mac AppStore was first announced, developers contemplated raising their prices to compensate for Apple taking a 30% cut of the revenue (compared to <10% for most other providers), now developers are thinking the opposite … let’s lower prices. I don’t think that this will be as extreme as the “race to the bottom” on the iOS AppStore, as Mac applications usually take longer to build than there iOS equivalents. This is mainly because iOS has a more modern set of APIs, and on the Mac you have to support extras like Drag and Drop, Keyboard Shortcuts etc.

I think that Mac AppStore application pricing will fall into 4 main categories:

Application Sales:

The simple fact is that people are more willing to give their payment details to Apple, rather than entering them on an indie developer’s website. If, and it is a big if, you get a prime place on the Mac AppStore (featured,top 25s etc) your sales are likely to be huge. For all the other applications on AppStore, time will only tell if it dramatically increases sales beyond the number of sales gained from the security of purchasing through Apple. I do believe however that non MAS sales will suffer a lot. The people that currently purchase applications online are likely to be “tech savy”, and therefore they will know about the MAS. Why would these users not switch to purchasing all of their applications through Apple? the fact is they will.

Hello AppStore bye bye Serial codes:

There are a few benefits of distributing applications through the AppStore rather than handling distribution yourself. One of the major pains is payments and serials, which can take up a considerable amount of an application’s development time. This along with handling updates, is now removed from a developers workload with the introduction of the MAS, saving developers time and a lot of headaches.

Conclusion:

On the whole I can only see the Mac AppStore being a positive thing for Mac users and developers alike. Developers have a central place to sell their products from, and they don’t have to worry about getting it listed on numerous application sites. Users will have an application (pre installed on their Mac!!!) which will allow them to search, view and securely purchase thousands of applications using just their Apple ID.

This could be a very big year for the Mac…

Detecting Multitouch Gestures in iOS

Before iOS 3.2 was introduced on the iPad (and latter with iOS 4.0 on the iPhone and iPod Touch), interpreting touch events as different gestures was an awkward task, and relied upon subclassing UIView, and then implementing the following methods.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

If you were trying to detect if a user was dragging a view (or panning as Apple would say), you would usually implement touchesBegan:withEvent: to start dragging the piece, touchesMoved:withEvent: to adjust the view’s frame, and then touchesEnded:withEvent: and touchesCancelled:withEvent: to stop detecting the drag. While implementing dragging was not too complex, trying to detect a more advance gesture such as a swipe or pinch was a lot more complex … and a lot of hard work to make it replicates Apple’s version of the gestures accurately.

Thankfully Apple created UIGestureRecognizer:

UIGestureRecognizer is an abstract base class for concrete gesture-recognizer classes. A gesture-recognizer object (or, simply, a gesture recognizer) decouples the logic for recognizing a gesture and acting on that recognition. When one of these objects recognizes a common gesture or, in some cases, a change in the gesture, it sends an action message to each designated target object.

Taken from Apple.

As UIGestureRecognizer is an abstract class, you will never use it directly. You will however use one of its subclasses, that have been designed specifically to capture a specific gesture.

So let’s take UIPanGestureRecognizer for an example, and we will use it to move a view around.

Our example view controller has a view (obviously), and this has a subview called panView, which is the view we will move around.

First thing that you will need to do, is create a pan gesture recognizer (UIPanGestureRecognizer) and add it to the panView. This will allow you to detect the gesture. To get informed about the gesture getting detected, you have to set the view controller as the delegate, and then have it call the panViewWithGestureRecognizer: selector. (Note: You can set any object as the delegate, as long as it implements the UIGestureRecognizerDelegate protocol. For this example the view controller makes sence.)

UIPanGestureRecognizer *panGesture = nil;
panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panViewWithGestureRecognizer:)];

[panGesture setMaximumNumberOfTouches:2];
[panGesture setDelegate:self];

[panView addGestureRecognizer:panGesture];
[panGesture release];

panViewWithGestureRecognizer: will get called when the gesture changes state, the possible states are:

For this example we only care about if gesture began (UIGestureRecognizerStateBegan) or has changed (UIGestureRecognizerStateChanged). When a pan gesture happens (begins or changes) we want to move the center of panView to be underneath the users finger, thus dragging the piece.

To do this we implement panViewWithGestureRecognizer: in the following way.

- (void)panViewWithGestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer {

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {

        CGPoint translation = [gestureRecognizer translationInView:[panView superview]];

        [piece setCenter:CGPointMake([panView center].x + translation.x, [panView center].y + translation.y)];
        [gestureRecognizer setTranslation:CGPointZero inView:[panView superview]];
    }
}

What makes this super easy is the convenience method translationInView:, which is found on UIPanGestureRecognizer. This gives you the value of where the center of the panView should be, without having to calculate it yourself. We then need to set the translation back to zero using setTranslation:, so when we calculate the next gesture, it will be from the new position of the panView. And that’s all there is to it.

As mentioned before there are a few gesture recogniser that have already been prebuilt for you to use, and you can even add multiple gesture recogniser to the same view. If you do this, you will want to implement:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

This simply allows you to specify if a gesture should be detected alongside another gesture e.g. a pinch and a rotation gesture. If Apple’s pre-built gesture recognizers are not enough for you, you can always create your own subclass of UIGestureRecognizer.

"Back to the Mac" - Thoughts and Predictions

Apple are looking to close off the year (in terms of keynotes anyway), with Steve Jobs talking about the Mac. The 4 keynotes previously in the year, focused on the iPad, iPhone and more recently the iPod line up.

If pictures paint a thousand words, the invitation clearly shows a lion, so one would assume that this event will be the unvaling of Mac OS 10.7 Lion.

As I like guessing a bit too much, here are my predictions for what we will see in Mac OS 10.7.

What I think will be in it:

What might be in it:

What needs to happen but won’t:

Other than Mac OS X, there is more than likely going to be a Mac hardware announcement along side iLife/iWork 2011. The MacBook Air seems to be the safe bet, but I also expect the entire MBP line to get a speed bump … Can I wish for USB 3.0?

One more thing … Maybe we get to find out what the “revolutionary feature” is.

Core Animation using blocks

Previously I have written a blog post about doing simple animations with UIViews, which you can find here. Starting in iOS 4.0 you can now do this with blocks.

Blocks have two major benefits (although there are more):

The most common method that you will use to animate views using blocks, is the following class method on UIView:

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;

This method allows you to set a time interval, along with an animations block and a completion block.

Let’s say we have a UIView variable called redView.

redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
redView.backgroundColor = [UIColor redColor];

We will then add redView as a subview of the view controller’s view.

[self.view addSubview:redView];

A common situation you may find your self in, is when you finish animating a view (e.g. changing its alpha), you would then want to remove it from it’s superview, and then release it from memory.

So if you had (for example) a method called animate to trigger off the animation, you would need to add an “animation did stop selector” to the animation. In the following example I have called it cleanUp.

- (void)animate {
    [UIView beginAnimations:@"" context:NULL];
    [UIView setAnimationDuration:5.0];
    [UIView setAnimationDidStopSelector:@selector(cleanUp)];
    [redView setAlpha:0.0];
    [UIView commitAnimations];
}

- (void)cleanUp {
    [redView removeFromSuperview];
    // I do release and = nil on the same line as a coding convention
    // so I don't forget to "nil" the variable
    [redView release], redView = nil;
}

Although this works well enough, it does mean that your code is split up into the animation code and the (completion) clean up code. If you end up doing this a lot, your code can end up becoming very fragmented and hard to follow.

Using blocks we can do the following:

- (void)animate {

    [UIView animateWithDuration:5.0

        animations:^{
          redView.alpha = 0.0;
        }

        completion:^(BOOL completed) {
          [redView removeFromSuperview];
          [redView release], redView = nil;
        }];
}

This keeps things nice and simple, and it means that you can easily see what code will be executed when the animation completes.

All of the animations you wish to do are passed in using a block:

^{
  redView.alpha = 0.0;
}

This block takes no arguments, and it also does not have a return type (so it defaults to void).

Instead of calling the cleanUp selector, we can simply pass in a completion block:

^(BOOL completed) {
  [redView removeFromSuperview];
  [redView release], redView = nil;
}

This block takes one parameter, which is a BOOL signifying if the animation has completed when the block is executed. In this example we ignore the completed variable, and we assume that the animation has completed for simplicity reasons. In the body of the block we do same as we did in the cleanUp selector, we remove redView from its super view and then release it from memory.

In some situations you won’t need to use blocks for Core Animation, but when you do, you will find it cleans up your code no end.

Apple's Master Plan

There is a theme coming from Cupertino, which was made slightly more apparent yesterday when they removed storage from the Apple TV … the master plan.

Apple are clearly going for the “your family has one master computer, and you sync lots of (smaller/lower cost) devices with it” distribution model … all of these devices are available from Apple. iPads are replacing laptops (for some), and people have long bought into the iPod revolution to play there digital media on the move. The AppleTV is a bit different as you can stream rented content from Apple to it, but the only way to get your own content on it, is to stream it from another device. This would either be from your computer, or an iOS device which you have already synced with your computer.

Although “the cloud” is clearly the future, it isn’t yet ready for prime time. Until everyone in their normal every day lives has access to a (constant) high speed internet connection, the cloud is merely a pipe dream in terms of using it for all of your data driven tasks.

Don’t get me wrong, the clouds time will come, but in the next 5 years? … I’m not so sure.

At the moment client applications (native applications that sync with a server and then cache the data for offline use), are the correct implementation for the moment. As far as streaming movies go, Apple knows that all AppleTVs will live in a home, and therefore (hopefully) have the bandwidth required to play HD footage.

Although people will disagree, the master plan is probably the right choice for the start of this decade, but the cloud’s time will come.

Page 7 of 9