Blocks/Closures are fragment of code that can be executed along-with/in-between another section of code, by passing them to those sections through method arguments/variables/properties. There the Blocks/Closures will be executed as next line of code from where they are invoked. Blocks can return like normal methods
Example 1:
How to create a block/closure ?
1) Define Block/Closure data type
// create types globally
Objective C Syntax: typedef returnType (^blockname>)(arguments);
typedef void(^DisplayMessage)(NSString *message);
Swift Syntax: typealias blockname = (arguments) -> returnType
typealias DisplayMessage = (message:NSString) -> Void
Objective C:
-(void)displayMessageWithHandler:(DisplayMessage)handler
{
handler(@" The execution of block of code started "); // block of code invoked
}
Swift :
func displayMessageWithHandler(handler:DisplayMessage) -> Void
{
handler(message: " The execution of block of code started ") // block of code invoked
}
3) Invoke the method
Objective C:
[self displayMessageWithHandler:^(NSString *message)
{
// block starts
// block starts
NSLog(@"%@",message); // displays " The execution of block of code started "
// fragments of code written here will be executed ...
// statement n
// statement n+1
// ......
// block ends
// block ends
}];
Swift :
self.displayMessageWithHandler
{ (message) -> Void in
// closure starts
println(message)
// fragments of code written here will be executed ...
// statement n
// statement n+1
// ......
// closure ends
// closure ends
}
In Swift Closures are alternatives of Objective C Blocks. Blocks are known by name Closures in other programming languages too
The Advantage of using Blocks OR Closures are
- Alternative technique to delegate/callback
- Executable piece of code can be passed to a method/other sections and executed there
- Blocks along with Grand Central Dispatch (GCD) are one of the best and faster solutions for Multithreaded Web Service Access/ API integration designing [ (3) this will be explained with the help of an Example code in a separate post ]
Example 2:
This is a Simple sample code that demonstrates how blocks/closures can be passed and executed. Here blocks/closures acts as a sole decision maker of Bubble Sort implemented in a method body. Here blocks returns a BOOL type
1) Create block/closure types
Objective C:
typedef BOOL(^CompareBlock)(NSNumber *number1,NSNumber *number2);
Swift :
typealias CompareBlock = (number1:NSNumber, number2:NSNumber) -> Bool
2) Creating Category/Swift-Extension for NSMutableArray to implement sorting
1) Create block/closure types
Objective C:
typedef BOOL(^CompareBlock)(NSNumber *number1,NSNumber *number2);
Swift :
typealias CompareBlock = (number1:NSNumber, number2:NSNumber) -> Bool
2) Creating Category/Swift-Extension for NSMutableArray to implement sorting
Objective C:
@implementation NSMutableArray (sortArrayCategory)
-(NSMutableArray*)sortListWithSortHandler:(CompareBlock)compare
{
/* Bubble Sorting */
for(int j = 0; j < (self.count - 1); j++)
{
for(int i = 0; i < (self.count - 1); i++)
{
if(compare(self[i],self[i+1])) // Calling the block = Executing the piece/block of code
{
[self exchangeObjectAtIndex:i withObjectAtIndex:i+1];
}
}
}
return self;
}
@end
Swift :
3) Create Array with list of numbers and Call the Category method
Objective C:
extension NSMutableArray /* Category in Objective C */
{
func sortListWithSortHandler(compare:CompareBlock) -> NSMutableArray
{
/* Bubble Sorting */
for(var j = 0; j < (self.count - 1); j++)
{
for(var i = 0; i < (self.count - 1); i++)
{
if compare(number1: self[i] as NSNumber,number2: self[i+1] as NSNumber) /* Calling the Closure = Executing the piece/block of code /*
{
self.exchangeObjectAtIndex(i, withObjectAtIndex: i+1)
}
}
}
return self
}
}
3) Create Array with list of numbers and Call the Category method
Objective C:
NSMutableArray *numberList = [NSMutableArray arrayWithObjects:@300,@100,@1000,@500,@200,@100,@2000,@4000,@2300, nil];
[numberList sortListWithSortHandler:^BOOL(NSNumber *number1, NSNumber *number2)
{
/* This block of code decides the type of sort Ascending OR Descending. It plays the role in making comparison for Bubble sort. Ascending if '>' and Descending if '<' is used */
return (number1.integerValue < number2.integerValue);
}];
Swift :
Inside blocks : Global variables , Global methods, Local variables inside method scope and imported constants can be referred. Among the variables only global variables are mutable by default. We need to make local variable mutable using keyword __block before the variable. It is recommended not to use the Mutable Arrays of __block type
Example 3:
__block int count = 100
Blocks/Closures and Memory management
var arrayList:NSMutableArray = [ 1200, 200, 3400, 5000, 800, 100, 9900]
arrayList .sortListWithSortHandler { (number1, number2) -> Bool in
/* This enclosed Closure decides the type of sort Ascending OR Descending. It plays the role in making comparison for Bubble sort. Ascending if '>' and Descending if '<' is used */
return (number1.integerValue < number2.integerValue)
}
Variable and Method accessibility in Blocks/Closures:
Example 3:
__block int count = 100
[self sampleBlock:^(......)
{
count = count++; // No error. Hence variable can be mutated
}];
Blocks/Closures and Memory management
- Copying blocks creates strong reference to object variables used within the blocks
- If Instance variables that are out of block's scope are used inside the block, those variables are strongly referenced by default
Blocks/Closures Uses and Possibilities
- Simultaneous enumeration and iteration through Collections
- Web Service / API access : Success and Failure Completion handlers - ( best if used along with GCD )
- As Callbacks
- Blocks can return another block
- Blocks can have another block as parameter
- Nested blocks is possible. But has to be implemented with great care ! developer needs to avoid memory leaks / retain cycles / reference related problems
- Blocks can be added to Array. Here also developer needs to avoid memory leaks / retain cycles / reference related problems