Sunday, December 8, 2013

Understanding ios block

Syntax
Blocks for objective c is similar to anonymous functions javascript, one can pass it as parameters of methods or return it from methods. Blocks have a typed parameter list and an optional return type. Block can be assigned to a variable and then be called as a function. The syntax of block follows C convention instead objective C, so it uses ',' to separate parameter, and use () to invoke a block.

Declare a block is similar as declare a function pointer, you can specify the return type and parameter types, but not the parameter names as shown below:
NSInteger (^mathOperation)(NSInteger, NSInteger);
void (^simpleBlock)(void);

Likes any other variables, the block variable can be assign to a value as shown below, note the parameter names are set in the block definition. However, the returning type specification is optionals, if missing it is inferred from the actual return type. To specify return type, it needs to be put after ^
NSInteger (^mathOperation)(NSInteger x, NSInteger y) = ^NSInteger(NSInteger x,NSInteger y){    
  return x + y;
}; 

void (^simpleBlock)(void) = ^{
        NSLog(@"This is a block");

    };

Another point is the parameters in block type definition uses ',' to separate each other, like C convention as shown below
NSInteger sum = mathOperation(1,2);

Note for block parameter type declared in method declaration is different from block variable, it moves the parameter name to the end of the declaration, like shown below. 

-(void) myMethodTakeBlockAsParameter: (NSInteger(^)(NSIntegerNSInteger))mathOperation;

When actually call the method, do not specify the return type, but specify the parameter names as below


 [self myMethodTakeBlockAsParameter: ^(NSInteger int1, NSInteger int2){
      return int1+ int2;
   }];


Variable Enclosing Scope
Block can access the data within its definition scope, similar to javascript enclosure function. If you implement a method and that method defines a block, the block has access to the local variables and parameters of the method (including stack variables), including instance variables. This access is read-only, but if a variable is declared with the __block modifier, its value can be changed within the block. Even after the method or function enclosing a block has returned and its local scope has been destroyed, the local variables persist as part of the block object as long as there is a reference to the block.

By default, the value is captured when the block is defined and is read-only. This means that if you change the external value of the variable after defining the block, then the value captured by the block is unaffected by the change. In below example, the anInteger's value in block is still 42:

    int anInteger = 42;
    void (^testBlock)(void) = ^{
        NSLog(@"Integer is: %i", anInteger);
    };
    anInteger = 84;
    testBlock();

If you need to change the value of a captured variable from within a block, you can use the __block storage type modifier on the original variable declaration. This means a live instance is used by the block and the original variable scope. For example if define the above variable as
__block  int anInteger = 42;
then the output will be 84.

When to use block
1. to enumerate NSArray or NSEnumerate object
enumerateObjectsUsingBlock

2. to specify a callback method as function parameter, such as completion callback block
3. To use by dispatch queue to specify a task to run sequentially or concurrently in sync or sync ways

No comments:

Post a Comment