Delegates are very useful at times but can be very hard to maintain at other times. With iOS 4, Apple introduced a functional programming aspect to it’s object oriented language, Objective C. (Prior to iOS 4, you could technically use blocks using the plausible blocks toolchain.) In this piece of open source code, we will explore how blocks can really simplify your code by avoiding un-necessary callback delegates.

If you have done iOS development, you would definitely have used, UIAlertViews and UIActionSheets. How many times have you used an UIAlertView twice in the same controller? How many times have to made the mistake of handling the delegate callback in a wrong way? i.e., you write code to handle the callback of AlertView1 but, by oversight it handles the callback of AlertView2. One way to avoid this problem is to tag your alertviews and check the tag in the delegates. However this is a bit clumsy and not an object oriented way of doing it. Let’s see how we can do this efficiently using blocks.

Say hello to blocks


How easy would it be to show an alertview and write the handler then and there without implementing a delegate protocol? Well now you can, with this category addition.

UIAlertView alertViewWithTitle:@"Test" 
                            message:@"Hello World" 
                  cancelButtonTitle:@"Dismiss" 
                  otherButtonTitles:[NSArray arrayWithObjects:@"First", @"Second", nil]
                          onDismiss:^(int buttonIndex)
     {
         NSLog(@"%d", buttonIndex);
     }
                           onCancel:^()
     {
         NSLog(@"Cancelled");         
     }
     ];

With the block based code, you are essentially passing the code that has to be executed on the delegate handler right into the method as a block parameter. As you see the above code, you realize that, instead of implementing a callback delegate, you are passing a couple of code blocks that has to be executed when certain buttons are tapped. This way your view controller code remains cleaner without un-necessary callback delegates.


As a matter of fact, the source code also contains an equivalent implementation for UIActionSheet and a bonus method to invoke an action sheet for choosing a photo.

With just a few lines of code, you can display a photo picker that automatically displays necessary buttons depending on the device and allows the user to pick an image.

[UIActionSheet photoPickerWithTitle:@"Choose an avatar" 
                             showInView:self.view 
                              presentVC:self 
                          onPhotoPicked:^(UIImage* image) 
     {
         NSData *data = UIImagePNGRepresentation(image);
         [data writeToFile:@"/Users/<username>/Desktop/test.png" atomically:YES];
        // or upload the image to your server
     }
                               onCancel:^
     {
         NSLog(@"Cancelled"); 
     }];

Source Code


The complete source code is available on Github here. Clone it or fork it or do whatever you want* with the code.
https://github.com/MugunthKumar/UIKitCategoryAdditions

Integrating it into your app

To add the code into your app, just clone the project and drag the folder MKAdditions into your project. Make sure to copy the added files. Start using the methods in the class right away.

Licensing

As always, you can do whatever you want with this code, whether commercial or non-commercial. But while you redistribute or enhance this code or for the repository, do maintain a link back to this blog post.

Mugunth

Follow me on Twitter

  • http://www.facebook.com/1ChuckSaldana Carlos Saldana

    Very clever!

  • Pingback: iOS Code: Block based performSelector | MK Blog

  • http://profiles.google.com/slatvick Slava Bushtruk

    Made some change. Trying to commit back now and then will pull request. :)

  • Pingback: Blocks Party at Under The Bridge

  • http://www.facebook.com/people/Lewis-Anderson/802129860 Lewis Anderson

    Very useful. I just downloaded the source and used the UIActionSheet methods in my app.

    Thank you sir!

  • http://LuminaryApps.com Joe Strout

    Thank you, very handy.

  • http://twitter.com/eodsoft Nikolai Sander

    Thanks a lot!

  • http://twitter.com/jdruid Joshua Drew

    has there been any issues with saving the files to the nsdocument directory with the image picker

  • Harry Jennerway

    Excellent resource. Delegates are so clunky. Thanks.

  • Jason

    Is it possible to use your UIActionSheet Category to showFromRect:, or does it only allow for inView? 

    If it’s possible to use your cat to showFromRect: could you explain how? 

    Thank you! This category is awesome. 

    • Jason

      Also, when using your category in iOS 5 with arc enabled, the delegate [self class] receives a warning. Should it be replaced by nil? 

      • Anonymous

        It doesn’t work with ARC. I should rewrite it.
        As of now it doesn’t support showFromRect:

        • Eli

          Is this category works on iOS5? How? I get warnings on delegate:[self class] if I replace this with delegate:nil then I blocks are not running.
          Any idea?

  • Bert

    This is very elegant. Thank you very much. 

  • dbv

    Shouldn’t the delegate be ‘self’ instead of ‘[self class]‘ in UIActionSheet+MKBlockAdditions.m?

  • ereedllc

    Very nice examples, thanks. However, I’m confused by the UIAlertView example. A UIAlertView constructor with the given signature (alertViewWithTitle: …) doesn’t exist, what am I missing? 

  • RyanG

    Thanks for this! Works great and makes things much easier and cleaner

  • Pingback: block based code « v: drive

  • Jidolstar

    Thank you!

  • http://twitter.com/chandrahasan4u Tagore Chandrahasan

    Hi Mugunth, great stuff to make things simple. I found this crash after I integrated into my app, but same happens in your Sample code also.

    [UIKitCategoryAdditionsViewController retain]: message sent to deallocated instance.

    Crashing in photoPickerWithTitle: method of ActionSheet, at _presentVC = [presentVC retain];

    Selecting Photo Library and cancelling, repeating this 3 to 4 times, crashes. Please help me fix this.

    • MugunthKumar

      This library is not arc ready.

      • http://twitter.com/chandrahasan4u Tagore Chandrahasan

        I am not using ARC

      • http://twitter.com/chandrahasan4u Tagore Chandrahasan

        Ohk, got it fixed.

        While Cancelling the UIImagePickerController you are releasing _presentVC and again releasing just before retaining, there by you are releasing twice where as you retained only once. Making _presentVC = nil, while releasing in ImagePicker Cancel method, solved the issue.

        Hope I made sense :)

        Thank you very much.