MultiThreading in iOS


Blocks are important in iOS programming because they are used to implement multithreading with GCD (Grand Central Dispatch).  A block is a chunk of code contained in {}.  To indicate the beginning of a block use a caret (^). Here is a block that prints a string.

^{
    NSString *name = "Batman";
    NSLog(@"My name is %@", name);
};

We use the caret (^) character to define the beginning of a block literal, and if there are any arguments they are contained in () followed by the block code itself contained in {}. An example of a block that takes an int as an argument and returns the square value.

^(int value){
    return value*value;
}

You don’t have to declare the return type of a block, it can be inferred from the code in the block. Most of the time we pass the block to a method directly, but we can also assign it to a block variable. The syntax for declaring a block variable is “return_type (^name) (arguments)” If we declare a block variable “square” and assign to it the block we used in the previous example, it would look like this.

int (^square) (int) = ^(int value){
    return value*value;
};

You can call this block just like a function.

int square_value = square(5);

We can also create a type definition for a variable that holds a block by using typedef. The syntax is similar to declaring a block variable name “typedef return_type (^type_name) (arguments)” Then we can declare the block variables with “type_name block_name = ^(arguments){…}”

Blocks are closures, therefore they have access to local variables when the block is created. Local variables are read only. If you want to be able to change the value of local variables, they need to be declared with __block.

To implement multithreading in iOS we use GCD (Grand Central Dispatch). Any operation that takes a long time to execute might lock the UI (User Interface) while it is being performed. For example, anything network related, like getting an image from a remote server. If the image is large enough, it might take a minute or two to download. If we don’t use a different thread for downloading the image, the whole app will be locked for the duration of the time it takes to download the image. In cases like this it is a good idea to use GCD to improve the user experience. This is where blocks become very useful to programmers.

GCD is a C API, therefore it is not object oriented API. The most basic use of GCD is to create a queue, and then to put blocks on that queue to be executed in a different thread by the system. The function used to create a queue and put a block on one are as follows

//to create a queue
dispatch_queue_t dispatch_queue_create(const char *label, NULL);

//to put a block on a queue
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block):

^dispatch_block_t is a prototype of blocks submitted that takes no arguments and doesn’t return anything. Let’s say we have a method that downloads an xml file from the internet.

-(void)fetchXML
{
    NSString *URLString = @"example.com/example.xml";
    NSURL *URL = [NSURL URLWithString:[URLString
                        stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
    NSData *dataXML = [NSData dataWithContentsOfURL:URL];
    NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:dataXML];
    [xmlParser setDelegate:self];
    BOOL success = [xmlParser parse];
    // test the result
    if (success) {
        NSLog(@"No errors");
    } else {
        NSLog(@"Error");
    }
}

To execute the fetching of the file on a different thread, we need to do the following modifications to our code. Create a queue and then put the code as a block on that queue.

-(void)fetchXML
{
    dispatch_queue_t fetchQueue = dispatch_queue_create("fetch xml", NULL);
    dispatch_async(fetchQueue, ^{
        NSString *URLString = @"example.com/example.xml";
        NSURL *URL = [NSURL URLWithString:[URLString
                         stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
        NSData *dataXML = [NSData dataWithContentsOfURL:URL];
        NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:dataXML];
        [xmlParser setDelegate:self];
        BOOL success = [xmlParser parse];
        // test the result
        if (success) {
            NSLog(@"No errors");
        } else {
            NSLog(@"Error");
        }
   });
}

There is just one more rule about using GCD for multithreading. When we have code that makes changes to UIKit objects, we need to dispatch that block of code in the main queue. The way to get the main queue is with “dispatch_get_main_queue”.

dispatch_async(dispatch_get_main_queue(), ^{....});

This will get you started with GCD. There are a lot more functions that you can use in GCD, consult the apple docs for more details on more advanced uses of GCD.

 

<script type=”text/javascript”>
(function() {
window._pa = window._pa || {};
// _pa.orderId = “myOrderId”; // OPTIONAL: attach unique conversion identifier to conversions
// _pa.revenue = “19.99”; // OPTIONAL: attach dynamic purchase values to conversions
// _pa.productId = “myProductId”; // OPTIONAL: Include product ID for use with dynamic ads
var pa = document.createElement(‘script’); pa.type = ‘text/javascript’; pa.async = true;
pa.src = (‘https:’ == document.location.protocol ? ‘https:’ : ‘http:’) + “//tag.perfectaudience.com/serve/529ebd713c619f6dda00000d.js”;
var s = document.getElementsByTagName(‘script’)[0]; s.parentNode.insertBefore(pa, s);
})();
</script>

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

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: