The iOS BlocksKit framework is awesome…

iOS Blocks are segments of code that can be passed around for later execution, in the same manner as a value or parameter can be passed to a function. At first, the syntax surrounding the use of blocks may seem a little confusing or unconventional, but once you begin to use them, you will find that they are in fact relatively straightforward and can speed up your development in many instances.

void (^simpleBlock)(void) = ^{ ..... eh??!!?

void (^simpleBlock)(void) = ^{ ….. eh?!!?

The really great thing about Blocks is that they give you a quick way to define a snippet of code that can capture and access the enclosing scope and its values, yet still be executed at later point in time when a particular event has occurred; all of this without the hassle of having to define excessive delegates or callbacks.

BlocksKit is a really neat framework which consists of lots of utility and category classes to make the use of blocks more accessible with existing framework classes such as NSDictionary and UIBarButtonItem. Below is just one example of where BlocksKit can come in handy.

Example: Presenting a ModalViewController

Let’s take the example of presenting an information screen (InfoViewController) to a user in a universal application. On an iPad we may want to present the information screen as a popover without a navigation bar, however, on an iPhone we may want to present the screen modally but provide the user with a ‘Done’ bar button in the navigation bar to dismiss the screen; furthermore, let’s say we wanted to do this without having to alter the .xib of the InfoViewController.

One method of doing this would be to modify the InfoViewController’s implementation to add a ‘Done’ button only if executed on an iPhone, such as:

- (void)viewDidLoad
{
    [super viewDidLoad];

    BOOL iPhone = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone);

    if (iPhone)
    {
        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissViewController:)];
        self.navigationItem.rightBarButtonItem = doneButton;
    }

    ...
}

This would result in a dismiss ‘Done’ button appearing in the navigation bar on an iPhone, but not when running on an iPad. Whilst this works, in some cases it’s not ideal that the InfoViewController itself has to be aware of how it is being presented, i.e. modally in this case; one would rather leave such logic to whatever is creating and using the view controller. Another (better) option would be to have the creator/user of the InfoViewController simply assign the navigation bar button itself and implement the button’s callback (selector) methods to dismiss the view controller. The downside here is having to implement unnecessary callback methods which clutter your class for such a simple purpose.

This is where blocks can come in really handy. For little tasks such as these, blocks containing the necessary operations to execute at a later stage can be defined and assigned in one place where it makes sense. Below is one example of how the above exercise can be implemented using BlocksKit:

    BOOL iPhone = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone);

    InfoViewController *infoVC = [self.storyboard instantiateViewControllerWithIdentifier:@"InfoViewController"];

    if (iPhone)
    {
        UINavigationController *modalController = [[UINavigationController alloc] initWithRootViewController:infoVC];

        // Present the view controller modally
        [self presentViewController:modalController animated:YES completion:^{

            // This block gets executed once the info view controller has finished presenting.

            // Create the done button for the navigation bar and implement the block that gets
            // executed when the button is tapped.
            UIBarButtonItem *doneBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone handler:^(id sender) {

                // When the button is tapped, dismiss the view controller
                [modalController dismissViewControllerAnimated:YES completion:nil];
            }];

            [infoVC.navigationItem setRightBarButtonItem:doneBarButton animated:YES];
        }];
    }
    else
    {
        // Show as a popover view controller
    }

And that’s it! Make sure to check out the BlocksKit framework for many useful classes that can make simple tasks quicker and cleaner IMO.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s