Keeping the Static Analyzer Happy: Prefixed Initializers

The latest version of Xcode ships with LLVM 3.0 as it’s default compiler, and one of the first things that you will notice is that is a lot more thorough when it analyses your code compared to previous versions (which can only be a good thing). One thing that the static analyser now warns you about, is that you are over releasing objects that are returned from prefixed intalizer methods (init), such as in a category (for my previous posts on categories see here and here).

For example my NSString category has the following method:

- (id)MCSM_initWithComponents:(NSArray *)components 
seperatedByString:(NSString *)seperator;

And it’s implementation looks like this:


- (id)MCSM_initWithComponents:(NSArray *)components seperatedByString:(NSString *)seperator {

    NSMutableString *componentizedString = [NSMutableString string];

    NSUInteger i = 0;
    for(NSString *component in components) {

            if (i == 0) {
                    [componentizedString appendString:component];
            } else {
                    [componentizedString appendFormat:@"%@%@",seperator,component];
            }

            i++;
    }
    return [self initWithString:componentizedString];
}

This method takes an array of strings, and joins together using the separator parameter and can be used in the following way:

NSArray *components = [NSArray arrayWithObjects:@"one", @"two", nil]; 
NSString *string = [[NSString alloc] MCSM_initWithComponents:components seperatedByString:@","];
NSLog(@"%@",string);
[string release];

This would output:

one,two

As this method is in a category of NSString I don’t want it to clash with any other implementations. The common practise in Objective-C is to prefix categories methods (due to the lack of namespaces), so I have with MCSM_. The issue is that the static analyser will now think that this method returns an autoreleased object, as the method does not begin with init, new, copy or alloc. This means when you release the object the static analyser will complain about you over releasing an object.

So how do you fix this?

To fix this you can tell the compiler that the method returns a retained object by using the source annotation NSRETURNSRETAINED, which means your interface would look like the following:

- (id)MCSM_initWithComponents:(NSArray *)components 
seperatedByString:(NSString *)seperator NS_RETURNS_RETAINED;

Instead of NSRETURNSRETAINED you can also use __attribute((nsreturnsretained)), which is a longer way of writing the same thing:

- (id)MCSM_initWithComponents:(NSArray *)components 
seperatedByString:(NSString *)seperator __attribute__((ns_returns_retained));

So thats all fixed? Unfortunately not quite yet. The static analyser will now complain about a memory leak, as we have allocated a NSString by doing [NSString alloc], but then it isn’t referenced again in our code. For a method that begins with init, the static analyser knows that the method consumes the variable (which means it releases the parameter upon completion), and that is the behaviour we need.

To do this we have to use the source annotation __attribute((nsconsumesself)) in conjunction __attribute((nsreturnsretained)), which means your interface will look like:

- (id)MCSM_initWithComponents:(NSArray *)components 
seperatedByString:(NSString *)seperator __attribute__((ns_consumes_self))__attribute__((ns_returns_retained));

And that will fix it.

Summary

You don’t need to use the source annotations if your code obeys the Objective-C naming conventions, but in certain circumstances like the one above you need to help the Static Analyser do its job. As LLVM forms the the backbone of Automatic Reference Counting (ARC), you still need to do this even if your not retaining and releasing memory yourself.

Steve Jobs 1955-2011

Having never met the man, it does feel strange that I am so deeply sadden by Steve Jobs passing, and I suppose that is because what I do today is really down to him. Not only did Steve Jobs have the vision to create the Mac, iPhone and iPad that are in front of me on my desk, he also had the passion to make me want them too.

Looked up to by millions, Steve Jobs was a charismatic visionary, who will go down as one of the greatest, if not the greatest CEO of all time. Not only did he start the computing revolution when he founded Apple in 70s, in his second stint as Apple CEO he brought a company on the brink of bankruptcy to be the most valuable company in the world in just under 15 years. Time and time again he ripped up the rule book and released product after product that change the world for good.

I could go on about how he changed the world but you already know that, and there are plenty of other articles that put it better than me. What I would like to say is that Steve Jobs’ passing has reiterated 3 things to me:

Find what you love

You’ve got to find what you love. And that is as true for your work as it is for your lovers.
Steve Jobs, Standford Speech (2005)

Don’t settle for second best, this is as true as it is for work as it is for love. You need to find what you love doing, and do that. If it makes you millions then thats great, but if it makes you happy then thats what counts.

Work hard to make it simple

That’s been one of my mantras - focus and simplicity. Simple can be harder than complex: you have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains.
Steve Jobs, Interview with Business Week, 1998

If you design an make stuff like me, your appreciate that one of the things that Steve Jobs has proven, is that users are willing to pay more for simplicity.

My favourite Steve Jobs Quote is:

Design is not just what it looks like and feels like. Design is how it works.

This goes hand in hand with simplify, it has to appear simple to use and be simple to use. Attention to detail in every aspect of design is key to a successful product. Make this your Mantra.

All good thing must come to an end

No one wants to die. Even people who want to go to heaven don’t want to die to get there. And yet death is the destination we all share. No one has ever escaped it.
Steve Jobs, Standford Speech (2005)

No matter how visionary you are, no matter how much money you have in the bank, one day you will be gone. Not everyone like Steve Jobs has the chance to become a legend, but you do have the chance to leave a legacy.

Stay Hungry. Stay Foolish.

Let's Talk iPhone Keynote Predictions

So tomorrow is the day that we finally get to see the successor to the phenomenally successful iPhone 4, but what is going to be new?

iOS 5

The one thing that the new iPhone is guaranteed to will ship with iOS 5. If you have not already seen the WWDC Keynote (if not why not?) then you already know whats coming in iOS 5. As a reminder you can look on Apple’s Website. The biggest change is how notifications work, they are less obtrusive and are all visible in one place. The other change that you will notice straight away (if you also have friends running iOS 5) is iMessage. iMessage is Apple’s awnser to RIM’s Blackberry messagener. It allows you to send free message to other user’s iOS devices, and you also get the option of recieving sent, received and read receipts.

iCloud

Although strictly speaking part of iOS 5, iCloud is a headline feature all of it’s own. It allows applications to store data “in the cloud” so it is accessible on all of your devices, be it iPhone, iPod Touch, iPad, Mac or one of those PC things. An important thing to note which differentiates iCloud from services like DropBox, is that applications can only see their own data (it is sandboxed by company). So for example, you can’t edit a photo in one application, and then upload it using another application by finding the edited image on the file system, in fact as a user you can’t even see your iCloud file system at all!!

A5 Chip

The iPhone 4 has an under clocked version of the iPad’s A4 processor, so it would make sense that new iPhone will have an under clocked version of the iPad 2’s A5 processor. The A5 processor (on the iPad 2 at least) has two cores, which will make your iPhone experience a little bit more snappy.

8MP Camera

Not confirmed by anyone, but it would make sense (and would also be relatively cheap) to put a higher quality camera in the new iPhone. Bumping up the megapixel count for 5MP to 8MP is a logical step, and a few phones already contain this sensor.

64 GB of Storage

The iPhone has been stuck at 32GB of storage since the arrival of the 3GS, so I expect an upgrade to 64GB so I am able to carry half of music collection, instead of a quarter of it. (I could really do with a 128GB iPhone if you couldn’t tell)

iPhone 5 or 4S

If I was Apple, I would call it the iPhone 5 how ever minor the update is, and that is for 2 reasons:

  1. I think people are more likely to upgrade to an iPhone 5, as subconsciously it just sounds like a bigger update
  2. If it is called the iPhone 4S, then what is the next iPhone going to called? The 6th iPhone surely can’t be called the iPhone 5. (I know there has been a 3GS, but that was because Apple called the 2nd iPhone, the iPhone 3G)

Other Updates

In addition to the iPhone, I expect the iPod Touch to get an update so it’s specifications are inline with the new iPhone’s. I don’t think it will get a 8MP camera though, but we might even see a 128GB Model. If we do see a 128GB Model, I do expect the iPod Classic to retire to the gadget museum. If we don’t see a 128GB, I don’t expect to see an iPod Classic update anyway … does anybody still buy them?

The iPod Nano will also get a refresh for the holiday season, now wouldn’t it be amazing if that run iOS 5…

Adding Block Support to Existing Classes (Without Subclassing)

Blocks are great aren’t they? Amongst many other things, they allow you to put all your completion logic right next to where you call an asynchronous method. Apple has added block support for completion handlers in such APIs such as Core Animation, in fact I have already done a post on this previously. But what do you do, if the class you want to use is stuck in the past and still uses the older delegate style approach. This is where you have to write a method to handle all the delegate callbacks for a given class? Well thankfully there is a nice and clean way of adding block support to a class using a category.

I’ve previously written 2 posts on categories (which you can find here and here), and how they allow you to extend a class’s functionality by adding additional methods to it without subclassing it. The key word being methods (or indeed selectors if your getting technical), and not properties or instance variables. If you need to call a block after an asynchronous action has completed, you’re going to have to store it somewhere in the meantime, and that is the main focus of this post.

Take UIAlertView for example, you need to register for a callback when the user presses a button.

So you’d often have something like:

- (IBAction)showAlert:(id)sender {    
    UIAlertView *alertView = nil;

    alertView = [[UIAlertView alloc] initWithTitle:@"YES or NO"
    message:@"Select One" 
    delegate:self 
    cancelButtonTitle:@"NO" 
    otherButtonTitles:@"YES", nil];

    [alertView show];
    [alertView autorelease];
}

Then you would need to implement a method with the correct signature to handle it:

- (void)alertView:(UIAlertView *)alertView  didDismissWithButtonIndex:(NSInteger)buttonIndex {
    if(buttonIndex == 1) {
        // Do Something
    }
}

This may look fine in the above example, but in a real iOS application the callback method may have to handle lots of different alert views, and we still have the handler code separated from where we actually setup and show the alert view.

So how can we solve this?

We are going to add a completion handler to UIAlertView, which doesn’t return anything and takes the button index we get given by the UIAlertViews delegate method as a parameter. To keep things clean we will define our completion handler in our categories header: objc typedef void(^MCSMUIAlertViewCompletionHandler)(NSUInteger buttonIndex); So the first thing you will need to do is set the completion hander block on an alert view and store it for when we get the delegate callback. For this we will use the Objective-C runtime function: objc_setAssociatedObject.

The objc_setAssociatedObject function takes 4 parameters:

  1. The object that you want to add the association too, in this case the UIAlertView
  2. The unique key so you can retrieve the value later
  3. The value you want to associate, which in this case is the completion handler block
  4. The association policy, which tells the runtime wether this association retains, copies or assigns the value.

The best way to describe how this function works, is that it treats an object like and NSDictionary. It allows you to set a given value for a given key, but unlike NSDictionary you can specify if the value is assign, retained or copied.

To use this method you need to include the runtime header:

#import <objc/runtime.h>

And we will define our key as a constant to keep things tidy, and so we don’t make any typos later on:

NSString * const MCSMUIAlertViewCompletionHandlerKey = @"MCSMUIAlertViewCompletionHandlerKey";

Then in another category method on UIAlertView all you need to do is set the alert view as its own delegate, and store the block as an associated object:

- (void)MCSM_setCompletionHandler:(MCSMUIAlertViewCompletionHandler)handler{
self.delegate = (id<UIAlertViewDelegate>)self; 

objc_setAssociatedObject(
self, 
MCSMUIAlertViewCompletionHandlerKey,
handler,
OBJC_ASSOCIATION_COPY_NONATOMIC);

}

As the UIAlertView is now it own delegate, it will receive the alertView:didDismissWithButtonIndex: callback. In this method you will need to retrieve the completion handler block so you can call it with the button index argument. To do this you will need to use another Objective-C runtime function objc_getAssociatedObject

The objc_getAssociatedObject function takes 2 parameters:

  1. The object to retrieve the association from
  2. The unique key for the association

This will mean that you end up with a method looking like this:

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {    
    // Get the Handler
    MCSMUIAlertViewCompletionHandler handler = (MCSMUIAlertViewCompletionHandler)objc_getAssociatedObject(
    self,
    MCSMUIAlertViewCompletionHandlerKey);

    // If there is a handler call the handler
    if (handler) {
        handler(buttonIndex);
    }

    //Release the block by setting the associated object to nil
    objc_setAssociatedObject(
    self, 
    MCSMUIAlertViewCompletionHandlerKey, 
    nil, 
    OBJC_ASSOCIATION_COPY_NONATOMIC);
}

So now that we have added this category to UIAlertView, all we have to do is update the code that creates and shows the alert view:

- (IBAction)showAlert:(id)sender {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"YES or NO"
    message:@"Select One" 
    delegate:self 
    cancelButtonTitle:@"NO" 
    otherButtonTitles:@"YES", nil];

    [alertView MCSM_setCompletionHandler:^(NSUInteger buttonIndex) {
        if (buttonIndex == 1) {
            // Do Something
        } 
    }];
    [alertView show];
    [alertView autorelease];
}

You can grab the code for this on Git Hub here and have a play with it yourself.

Mac OS 10.7 Lion - My Favorite new APIs

So after months of waiting, Mac 10.7 has finally been released to the general public. Although it has been given some minor spit and polish on the UI front when compared to it’s predecessor Mac OS 10.6, most of the improvements are under the hood. Thankfully the majority of these changes have been made available to developers in the form of APIs. With that in mind I thought I would point out some of my favourite new APIs that I have been using in the developer previews.

NSPopover

NSPopover works a lot like UIPopoverController on iOS. You give an NSPopover an instance of NSViewController (or one of your subclasses), and you can then present this view controller in a popover.

- (IBAction)showPopoverFromButton:(id)sender {
// Create the popover
popover = [[NSPopover alloc] init];

//Set the content view controller
popover.contentViewController = popoverViewController;

popover.animates = YES;

//So we get told when the popover has closed
popover.delegate = (id<NSPopoverDelegate>)self;

[popover showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxYEdge];
}

The APIs for NSPopover are nice and simple, but in true Mac OS fashion the delegate callbacks take the form of NSNotifications rather than selectors.

- (void)popoverDidClose:(NSNotification *)notification {
    if ([notification.object isEqualTo:popover]) {
         [popover release]; popover = nil; 
    }
}

If you need to implement something like NSPopover in previous versions of Mac OS, then I recommend taking a look at MAAttatchedWindow.

CoreData

CoreData has had so many updates in Mac OS Lion it is hard to know where to start. Most of the API changes are to incorporate features that are needed to support Versions and iCloud Syncing. What this means is when you modify files Versions and iCloud only want to know the changes that have been made to a file, so they only need to store or transfer the differences between the original and the new file. This approach not only saves space (only the changes are stored, not another whole file), and it also means the versions of the file can easily be compared and contrasted (I am guessing that Apple uses GIT for this). If your application persists any data (and who’s doesn’t?), then you must look at CoreData as it gives you so many things for free.

NSOrderedSet

An ordered set, isn’t that just an array? Well in reality it is, it is an array that makes sure that the objects that it holds are unique and therefore not duplicated. That in itself isn’t that exciting, but what is exciting is that it allows you to have ordered Core Data relationships by simply ticking a box. These ordered relationships do incur a performance penalty over non ordered relationship, so don’t use them for the sake of it.

Concurrency

One of the major issues with CoreData is that NSManagedObjectContexts and therefore the NSManagedObjects that it contains, are not thread safe. In Lion NSManagedObjectContext has the initialiser method initWithConcurrencyType, which allows you to tell an NSManagedObjectContext to mange all of it’s interactions using its own private dispatch queue. This means by using Grand Central Dispatch you can reduce the complexity of concurrency when using CoreData in Mac OS 10.7.

Full Screen Windows

The full screen APIs are incredibly simple to implement (as long as your window resizes to the size of a user’s screen).

All you need to do is set the window’s collection behaviour to support full screen:

[window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];

This one line of code gives you the “full screen button” in the top right hand corner of the window.

If you want to make the window go full screen yourself, you just need to call the toggleFullScreen method on NSWindow:

[window toggleFullScreen:nil];

View based Table Views

My favourite new class is without a doubt NSTableCellView, as it allows you to use a (subclass of) NSView as a table view cell, rather than an NSCell (which is my least favourite class if you are asking). This makes things a lot easier to build custom UIs in a table cell, and also means it can have subviews such as NSButtons that can receive mouse events.

The two data source methods you must implement are:

- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView;

- (NSView *)tableView:(NSTableView *)aTableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;

Although this makes NSTableView a lot more like UITableView it is important to note that NSTableView doesn’t support sections (as you may have guessed by the numberOfRowsInTableView method not being called numberOfSectionsInTableView). To make things slightly more confusing, NSTableView does however support group rows. Group rows float above the non group rows below it, which means they behave like iOS section headers.

You can tell the table view that a cell is a group row by using the delegate method:

- (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row;

If you are creating a custom NSTableCellView in code, don’t forget you can override isFlipped to flip the coordinate system and make it like the iOS co-ordinate system.

Also don’t forget that as NSOutlineView is a subclass NSTableView, so it also supports view based cells.

In App Purchase

In App Purchase for iOS has been in the press for all the wrong reasons recently, but it is a great API for Mac OS X developers to have, so they can unlock different features in their applications. The API is very similar to it’s iOS counterpart besides when it comes to receipt validation. For more information on this I recommend watching the WWDC session 510, which is all about In App Purchase.

Push Notifications

Another feature ported across from iOS, but this time with less features. On Mac OS push notifications can only contain a badge value and not an alert and/or sound.

So thats a wrap up of my favourite new APIs in Lion, the standout ones for me being View Based Table Views and NSPopover. There have been so many updates I recommend looking through the change list, as you never know what you might find.

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. NSFileManger 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 lets say you have a Account Manager 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:

1) A subscription deal on the iPad 2) The iPlayer integrated into Apple TV

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.

Page 4 of 7