Blocks are feature added to C, Objective and C++ basically to create an object(some structure in case of c) without data member and single function in it.
They can be added to collections likeNSArray or NSDictionary. They can be passed around to methods or functions as if they were values.
They also have the ability to capture values from the enclosing scope, making them similar to closures or lambdas in other programming languages.
Block Syntax
^{
|
NSLog(@"This is a block");
|
}
|
braces indicate the start and end of the block.
Block with no argument taking and nothing returning:-
Ex:- here simpleBlock is a variable to store bloack its same like function pointer in C
void (^simpleBlock)(void);
simpleBlock = ^{
|
NSLog(@"This is a block");
|
};
|
You can also combine the variable declaration and assignment:
void (^simpleBlock)(void) = ^{
|
NSLog(@"This is a block");
|
};
|
After this assignment u can invoke the block as
simpleBlock();
Like calling function on function pointer.
Note: If you attempt to invoke a block using an unassigned variable (a nil block variable), your app will crash.
Blocks Take Arguments and Return Values
Example
double (^multiplyTwoValues)(double, double);
^ (double firstValue, double secondValue) {
|
return firstValue * secondValue;
|
}
|
firstValue and secondValue refers to passing arguments to the block same like passing argument to function.
Combined as
double (^multiplyTwoValues)(double, double) =
|
^(double firstValue, double secondValue) {
|
return firstValue * secondValue;
|
};
|
|
double result = multiplyTwoValues(2,4);
|
Blocks Can Capture Values from the Enclosing Scope
- (void)testMethod {
|
int anInteger = 42;
|
|
void (^testBlock)(void) = ^{
|
NSLog(@"Integer is: %i", anInteger);
|
};
|
|
testBlock();
|
}
|
In this example, anInteger is declared outside of the block, but the value is captured when the block is defined.
Example
int anInteger = 42;
|
|
void (^testBlock)(void) = ^{
|
NSLog(@"Integer is: %i", anInteger);
|
};
|
|
anInteger = 84;
|
|
testBlock();
|
output of the above program will be
Integer is: 42
It also means that the block cannot change the value of the original variable, or even the captured value (it’s captured as a const variable).
Use __block Variables to Share Storage
Use __block storage type when u want the value of captured variable within block should be change.
Example:-
__block int anInteger = 42;
|
|
void (^testBlock)(void) = ^{
|
NSLog(@"Integer is: %i", anInteger);
|
};
|
|
anInteger = 84;
|
|
testBlock();
|
output of this program will be
Integer is: 84
It also means that the block can modify the original value, like this:
__block int anInteger = 42;
|
|
void (^testBlock)(void) = ^{
|
NSLog(@"Integer is: %i", anInteger);
|
anInteger = 100;
|
};
|
|
testBlock();
|
NSLog(@"Value of original variable is now: %i", anInteger);
|
output will be
Integer is: 42
|
Value of original variable is now: 100
|
You Can Pass Blocks as Arguments to Methods or Functions
it’s common to pass blocks to functions or methods for invocation elsewhere. Just like passing function pointer on which passed function can call that function.
Blocks are also used for callbacks, defining the code to be executed when a task completes.
example:-
- (IBAction)fetchRemoteInformation:(id)sender {
|
[self showProgressIndicator];
|
|
XYZWebTask *task = ...
|
|
[task beginTaskWithCallbackBlock:^{
|
[self hideProgressIndicator];
|
}];
|
}
|
The declaration for the beginTaskWithCallbackBlock: method shown in this example would look like this:
- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock;
|
The (void (^)(void)) specifies that the parameter is a block that doesn’t take any arguments or return any values. The implementation of the method can invoke the block in the usual way:
- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock {
|
...
|
callbackBlock();
|
}
|
Method parameters that expect a block with one or more arguments are specified in the same way as with a block variable:
- (void)doSomethingWithBlock:(void (^)(double, double))block {
|
...
|
block(21.0, 2.0);
|
}
|
A Block Should Always Be the Last Argument to a Method
- (void)beginTaskWithName:(NSString *)name completion:(void(^)(void))callback;
|
This makes the method call easier to read when specifying the block inline, like this:
[self beginTaskWithName:@"MyTask" completion:^{
|
NSLog(@"The task is complete");
|
}];
|
More
Block objects are a C-level syntactic and runtime feature that allow you to compose function expressions that can be passed as arguments, optionally stored, and used by multiple threads.
You use a block when you want to create units of work (that is, code segments) that can be passed around as though they are values. Blocks offer more flexible programming and more power. You might use them, for example, to write callbacks or to perform an operation on all the items in a collection.