Home > DeveloperSection > Articles > Objective-C : Blocks

Objective-C : Blocks


iPhone iPhone  Ios  Objective C 
Ratings:
0 Comment(s)
 901  View(s)
Rate this:

Objective-C : Blocks 


Previously we learn about 'Pointers' :  Objective C - Pointers

 

Blocks are an Apple extension to the Objective-C language that were motivated by the desire to pass small pieces of code in API calls to the Grand Central Dispatch multithreading system. Grand Central Dispatch (GCD) works by making use of queues containing such small pieces of code, each representing a task or unit of work to be done. Blocks do not consist of a new programming discovery in Objective-C. They exist in other programming languages too (such as Javascript) with other names, such as Closures. Blocks have been available in iOS since version 4.


In subsequent iOS versions, Apple re-wrote or updated many framework methods so they adopt blocks, and it seems that blocks are going to be partly the future of the way code is written. But what are they all about really?

 

The basic idea of a block is to treat a small piece of code as if it were a value. The piece of code can then be passed as a parameter in messages or assigned to a variable. Eventually, at some future time, the code will be executed.


Using blocks, there is no need to adopt protocols, or implementing delegate methods that lead to much more code in a class. The best thing though, is that the callback procedure can directly access and use any variables existing locally in the scope where the block has been defined, so the need of passing data like we do in callback methods is eliminated.

 

Blocks are objects, so they can be stored to NSArray or NSDictionary data structures, as well as to be returned from methods, even to be assigned to variables.

 

[ Two facts are sure for every developer, even if someone has no idea about blocks.

First off, it’s certain that every one has used blocks, even without knowing it. That’s because Apple has adopted blocks especially as completion handlers to many important, commonly used methods.

Secondarily, thankfully or not, you don’t need to have deep knowledge on block programming in order to use them, just to understand how they work.]

 

Blocks have two great features:


1.       They can be executed in a later time, and not when the code of the scope they have been implemented is being executed.

2.       Their usage leads eventually to a much cleaner and tidier code writing, as they can be used instead of delegate methods, written just in one place and not spread to many files.

 

The most basic form of a block, known as a "block literal", consists of a caret character ("^"), followed by a set of curly braces that contain the actual code, as shown below:

    ^{        NSLog(@"Hi, I'm a block literal.");

    }

Blocks appear inline along with the rest of your code, inside a method or function.

 

A block declaration follows the next syntax pattern:

ReturnType (^blockName)(Parameters)

 

This is quite similar to a C function declaration, with one great exception: The caret (^) symbol, which indicates that the declared object is a block. Let’s see everything one by one:


  • ReturnType: Any data type Objective-C supports, or void if the block returns nothing.
  • ^blockName: Always remember that the block name is preceded by the ^ symbol. The block name can be any string you like, just like you name any other variable or method. Remember that both the ^ and the block name are enclosed in parentheses ().
  • Parameters: The list of parameters you want to pass on the block, just like you do when declaring methods. However, keep in mind an important notice: When you pass no parameters to block, then the void keyword should be always set. The arguments list must also be enclosed in parentheses.

·         And that’s all about declaring blocks. Here are some examples:

int (^firstBlock)(NSString *param1, int param2);
void (^showName)(
NSString *myName);
NSDate *(^whatDayIsIt)(void);
void (^allVoid)(void)
;
NSString *(^composeName)(NSString *firstName, NSString *lastName);

  

The use of the ^ symbol and all those parentheses may seem confusing at the beginning, but don’t worry. You just have to get used to it and do never forget the ^ symbol.

 

·         A special characteristic that the block declaration has, is that the parameter names can be omitted, and just keep the parameter types. Actually, adding parameter names to the declaration only helps developers to remember them, but it offers nothing to the compiler. So, all the above declarations could be re-written without the parameter names this time:

       int (^firstBlock)(NSString *, int);
void (^showName)(
NSString *);
NSDate *(^whatDayIsIt)(void);
void (^allVoid)(void)
;
NSString *(^composeName)(NSString *, NSString *);

 

Using or not parameter names is totally up to you. It’s not wrong to use them, nor to omit them as well. Usually, advanced developers familiarized with blocks do not write parameter names, just their types, but for beginners I think that helps a lot to have the parameter names written.

 

Let’s focus now on the block definition:

^(Parameters){
... block body ...
return ReturnValue (or nothing if the block return type is void)
};


As you see, no block name exists here. In block definition, parameter names are mandatory, unlike the block declaration where they are optional. Especially note that after the block body closing, the semicolon ; is added, as the whole block is considered as a variable. Don’t worry if you ever forget it; Compiler is there to remind it to you.


Here is a really simple example:

^(int a, int b){
        int result = a * b;
       
return result;
};


Of course, you are never going to use a block simply like this. The most possible cases is that the block definition result will be assigned to a variable, or that you’ll define the block using it as a completion handler, upon a method call (later on this).

 

Let’s see now a couple of examples on how you can assign block results to a block variable:

int (^howMany)(int, int) = ^(int a, int b){
    return a + b;
};

In this example, the parameter names have been omitted in the declaration, but they mandatorily exist on the definition. Once again, I underline the usage of the ^ symbol, and the ; at the closing of the block body.

 

Some other Examples:

Example 1:

      int (^howMany)(int, int) = ^(int a, int b){
      return a + b;
};   
NSLog
(@"%d", howmany(5, 10));

            // Output: 15

 

Example 2:

   NSDate *(^today)(void);
    today
= ^(void){
        return [NSDate date];
};
NSLog
(@"%@", today());

            // Outputs the today's date.

 

Example 3:

        float results = ^(float value1, float value2, float value3){
        return value1 * value2 * value3;
} (1.2, 3.4, 5.6);
NSLog
(@"%f", results);

            // Output: 22.848001

This is a more direct approach, as using the same command we define the block, we pass the parameter values and we assign the results to a variable.

 

Example 4: using a variable existing out of the block definition:

    int factor = 5;
int (^newResult)(void) = ^(void){
        return factor * 10;
};   
NSLog
(@"%d", newResult());

            // Output: 50

Now, you are considered to have taken the basic understanding and have set the ground for writing and using blocks.

 

Understanding the Full Syntax of Blocks


A block is similar to a C function, and can accept input parameters and produce a return value.

To see the similarities (and differences) between blocks and C functions, we can begin with a simple C function that adds two numbers together. We first define it:


int addTwoNumbersFunction(int a, int b) {

                      return a+b;}

Then we call it:

int c = addTwoNumbersFunction(3,4);   NSLog(@"Result is %d",c);

 

We will see on the console log:

Result is 7

 

A block is quite similar, although with a messier syntax:

int (^addTwoNumbersBlock) (int,int) = ^(int a, int b) {

                      return a+b;    }

And we can call it in the same way:

int c = addTwoNumbersBlock(3,4);

       NSLog(@"Result is %d",c);

 

We will see on the console log:

Result is 7

 

Looking at the code for defining the block, we have seen what's on the right side of the assignment statement before: this is just the literal block, including a declaration, in parentheses, of the input parameters:


int (^addTwoNumbersBlock) (int,int) = ^(int a, int b) {

                      return a+b;    }

 

On the left side we have the return value for the block, the caret declaring that this is a block along with the name of the variable we are assigning the block to, and a seemingly gratuitous indication of the fact that there are two input arguments, both integers. (But as to the last, the left side is declaring the variable and its type, while the right side is declaring and implementing the actual block.)

 

Although messy, it is not hard to understand--the real problem is remembering the syntax.

 

What we have done here is declared the variable addTwoNumbersBlock to have the type block (with return value of int and two input parameters, both int), and assigned an actual block to the variable.

 

And the compiler and runtime know that when they see a variable that has been declared as a block, that the code for that block should be called, with its input arguments, in the same way that the code for a C function is called.

 

 Next, we will learn about : Objective-C : Constants


Don't want to miss updates? Please click the below button!

Follow MindStick