facebook youtube pinterest twitter reddit whatsapp instagram

Blocks and Multithreading in iOS

When developing for iOS, there are several ways to deal with multithreading. You can create your own threads and do whatever you please, but there are various alternatives that will make your life much easier. In Snow Leopard, Grand Central Dispatch (GCD) was introduced, and it is the easiest and most efficient way to handle multithreading.

Before we start talking about Grand Central Dispatch, you first need to know what blocks are, since we will use them for our multithreaded app.

Blocks

In Objective-C, a block is a block of code that can be passed as an argument and treated as a variable. Blocks start with the character caret ^, followed by the arguments in parentheses, and then the actual code between curly braces.

NSDictionary *dictionary = [[NSDictionary alloc] init];
     [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
        self.label.text = value;
        if ([@"Last" isEqualToString:value]) {
            *stop = YES;
        }
    }];

Local variables declared outside the block can be accessed inside the block, although they are read-only. If you want to change its value, then you need to add __block to the variable declaration.

__block int totalIterations = 0;
NSDictionary *dictionary = [[NSDictionary alloc] init];
     [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
        self.label.text = value;
        totalIterations++;
        if ([@"Last" isEqualToString:value]) {
            *stop = YES;
        }
    }];

Just like in C, you can use typedef to create a type of variable that will be used to store a whole block of code.

typedef BOOL (^block_type)(int iterations);

Now, you can declare a variable of type block_type:

block_type block;
block = ^(int iterations) {
    BOOL finished = NO;
   
    for (int i = 0; i < iterations; i++) {
        NSLog(@"Inside block");
    }
   
    finished = YES;
    return finished;
}

Finally, you can call this variable like this:

BOOL isFinished = block(10);

Blocks in iOS can be really hard, so don’t worry if you get confused at the beginning. Unfortunately, blocks are really useful and as a developer you will need to use them quite a lot. They are mainly used for:

  • Enumeration.
  • View Animations.
  • Sorting.
  • Notification.
  • Error handlers.
  • Completion handlers.
  • Grand Central Dispatch

Grand Central Dispatch

GCD is a C API that works with queues of operations, and provides and manages FIFO queues to which your application can submit tasks in the form of block objects. It is really powerful, since you just pass a block of code to a queue, and it will eventually get executed without blocking any other threads and without having to manage threads yourself.

There are three kinds of queues:

  • Main: the application’s main thread.
  • Concurrent: if the device has multiple processors, tasks run concurrently and may finish in any order.
  • Serial: tasks execute one at a time in FIFO order.

The main thread is where you can touch the UI, otherwise, your app may crash and will behave badly.

The most important functions are:

  • dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr): with this function you create a new queue. attr is used to specify whether it is a concurrent or a serial queue. Pass NULL to create a serial queue, and DISPATCH_QUEUE_CONCURRENT for a concurrent queue.
  • void dispatch_async(dispatch_queue_t queue,dispatch_block_t block): puts a block in a queue.
  • dispatch_queue_t dispatch_get_current_queue(): to get the current queue.
  • void dispatch_queue_retain(dispatch_queue_t): use this function after getting the current queue to retain it.
  • dispatch_queue_t dispatch_get_main_queue(): returns the main queue.
  • void dispatch_release(dispatch_queue_t): to release the queue once it has finished executing all the blocks.

Example

Now that you know everything you need about blocks and GCD, I will show you a quick example to get an image from a URL and download it without blocking the main thread. Once it has finished downloading it, we will assign it to the UIImageView’s image property.

Create your project, and from the storyboard, add a UIImageView to your UIView and embed it in a UIScrollView.

Don’t forget to declare two IBOutlets (imageView and scrollView) to link your code to the storyboard. The only thing you need to do to download an image from another thread, is to add this to your view controller’s implementation file:

- (void)viewWillAppear:(BOOL)animated
{
    dispatch_queue_t downloadQueue = dispatch_queue_create("image", NULL);
    dispatch_async(downloadQueue, ^{
         NSData *imageData = [[NSURL URLWithString:@"http://www.example.com/example.png"]];
         dispatch_async(dispatch_get_main_queue(), ^{
             UIImage *image = [UIImage imageWithData:imageData];
             self.imageView.image = image;
             self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
             self.scrollView.contentSize = image.size;
         });
    });
    dispatch_release(downloadQueue);
}

Conclusion

Although blocks may be difficult to understand at first, once you get used to them you will find them very useful.

As for GDC, it really helps us, developers, to implement multithreading in a very easy way. If you have any doubts, please leave a comment!

Related Post(s)

  • Displaying Images in iOS

    Creating images from code is really easy, and although you can draw them in any UIView, they are almost always displayed using UIImageView, a UIView subclass. In this tutorial, I will show you how to

  • Playing Audio in your iOS App

    Due to the fact that the iPhone and iTouch are all about playing music, one would think that playing audio in iOS would be an easy task. Well, I hate to break it to you, but playing sound effects in

  • Alerts in iOS

    Alerts are used to display messages with important information about the application, such as error or warning messages. This tutorial will dive into the use of UIAlertView to create alerts and how t