Using Blocks in Objective C

Introduction

When programmers and developers from the other high level languages such as Java and other similar ones shifts to Objective C, Blocks is one of the most confusing concept. But trust me its the most important concept in Objective C which is extensively used in Objective C style programming. Moreover once you know the basics its becomes really easy to use it.You can explore the world of blocks to deeper level in Apple’s Developer Guide. This post majorly focuses on the concepts to get you started.

If you are a C programmer/developer then you must be aware of the concept of block programming. It’s a feature from C that is inherited into Objective C.

Advantages

Blocks have a many advantages that helps the developer to write more robust and effective code. Some of the advantages are as follows:

  • Easier maintenance of code.
  • Compile time type checking
  • No need for parameter mapping.
  • Code re-usability

These are few of the advantages you can explore more over the place to have a deeper understanding.

What are Blocks ?

So what are blocks ?

Blocks are basically a set of statements enclosed in the curly braces. In obj-C the initiation of a code block is represented with Caret(^) character followed by curly braces {} and terminated similar to other statements with a semi-colon.

Defining and Calling a Block

Block definition and Calling is similar to the concept of declaring a variable in a programming construct and calling a function in it.

return-type (^name-of-block)(Parameters) =
^return-type(Parameters){ Block Statements };

 

Lets try with an example. Suppose we have a block with no parameters and a return type of void that prints something to console.

void (^printSomething)() = ^{
        NSLog(@"Hello World!");
    };

 

The above code block prints “Hello World” to the console, a traditional way for any code construct to get started.

To make a call to the above code block, you can call that as a simple C function.

printSomething();

Now lets see something more relevant, say a code block that returns an integer sum of two arguments provided to the block.

int (^calculateSum)(int, int) = ^int(int a, int b){
        return a+b;
    };
    int sum = calculateSum(10,12);

Accessing Local Variables

Block have their own scope where they execute the statements. You can access class and local variables inside the block scope, but remember that you cannot alter those. That means the local and class variables used inside the scope of the block are read-only. If you try to do, the compiler will pop a red alert. Lets take an example that we referred in the previous section of calculating the sum.

int c = 10;
    int (^calculateSum)(int, int) = ^int(int a, int b){
        NSLog(@"Print the value of c variable: %d",c); //Correct
        c = a + b; // Incorrect - Compiler Error [Variable not assignable]
        return a+b;
    };
    int sum = calculateSum(10,12);

Block Variables

To make changes to the block level variables, Objective-C specifies a different property type for the block. It is __block. To alter the value of a particular variable inside the block its required that you create a local variable and assign address to it. This will help to manipulate the value of the variable inside the block scope.

int c = 10;
    __block int d = c; // block variable declaration
    int (^calculateSum)(int, int) = ^int(int a, int b){
        d += a + b;
        return a+b;
    };

    int sum = calculateSum(10,12);
    NSLog(@"Sum %d",d); // Gives 32.

In the above example we are assigning a value to d variable which is used, inside the scope of the block and then accessed outside the block to print the value. This is the way you can have variables used inside the block scope.

Use of TypeDef

Instead of declaring the blocks inside the code, you can actually declare it using the typedef identifier in C. This specific purpose helps to bring modularity to our code by implementing code re-usability. Lets see an example:

// In your header file use the typedef identifier to
// declare the block.

.h file
typedef void (^PrintSomething)();

.m file
PrintSomething print = ^void{
        NSLog(@"Print Hello World !");
    };
print();

The above approach helps a lot reuse the code at different places rather than clogging the code at one place only. Hence making it easier for the programmer/developer to maintain the code through out the application.

Using Block as Method Parameters

This one thing you will find a lot in the Objective C nowadays, methods with blocks as a parameter. It’s a great approach as it works as anonymous methods at hand, hence removing the need of unnecessary definitions. To get a better understanding lets refer to an example which will make things much easier for us. Lets consider a realtime example already defined in Objective C Foundation Framework:

We all have an idea of GCD feature, it helps to achieve the multithreading capability in our iOS applications.

dispatch_async(dispatch_get_main_queue(), ^{
       //statements to executed in this task
    });

As we can see that the dispatch_async() method takes two parameters, one is the queue on which this task is to be performed and other is a void block, the set of statements to be executed when this task is executed.

As you will move deeper into understanding of blocks you will notice that there is a lot of potential that can be used using this feature of Obj-C.

Memory Management

One of the main problems that we face while using blocks are the memory leaks. These leaks are hard to find in the application as they are getting generated inside the block so to avoid such kind of situation, follow the below approach:

Blocks are always created on the stack, which means they disappear from the stack as soon as they are finished executing. To save your block, you need to create a copy of it. After copy operation completes, it is copied to the heap so that it can be saved for the later use.

typedef int(^CalculateSum)(int,int);
@property(copy,nonatomic) CalculateSum sum;

Also you can use the autorelease property available to make environment release the block memory as soon as its finished with the task or the application does not require its services any longer.

One more thing that developers/programmers generally do inside a block is the use of self inside the code block. This is one of the major reason for memory leaks. To use self inside the block, create another variable with __block identifier which refers to the address of self.

__block ClassName *blckSelf = self;
    __block int total = 0;
    CalculateSum sum = ^int(int a, int  b){
        total = a + b;
        [blckSelf printSum:total];
    };

That’s all for now guys. I hope that this post will help you in figuring out the concepts. In case you have any issues please feel free to post a comment.

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