Objective C Blocks Sample Code

Objective C Blocks Sample Code

Written By: Debasis Das (19-Apr-2015)

In this post we will create sample codes for using blocks in an Cocoa Objective C Application

Block with 1 input Parameter and 1 return Type

int (^testBlock)(int) = ^int (int num)
{
    int multiplier = 7;
    return num * multiplier;
};
//    NSLog(@"number %d",testBlock(10));      //This will print 70

Block with 2 input parameters and 1 return type as int

int (^addBlock)(int, int) = ^int(int va1, int val2)
{
    return va1 + val2;
};
//    NSLog(@"addBlock %d",addBlock(10,12));  //Prints 22

Two input parameters and block definition

-(void)blocksSampleThree{
    float (^areaBlock)(float length, float breadth); //Declare the block variable
    //Create and assign the block
    areaBlock = ^float(float len, float brd) //Defines the return type to be float
    
    //areaBlock = ^(float len, float brd)
    //Does not define the return type. Defining the return type is not mandatory
    {
        return len * brd;
    };
    
    float newArea = areaBlock(10.87,87.65);
    NSLog(@"newArea is %2.2f",newArea);    //Prints 952.76
}

Block with No input Parameters

u_int32_t (^randomNumber)(void) = ^{
    return arc4random();
};
//    NSLog(@"random number is %d",(int)randomNumber);

Closures

-(void)blocksSampleFour{
    //Blocks can access to non local variables defined in the blocks enclosing lexical scope but outside the block itself
    
    NSString *firstName = @"John";
    NSString * (^getFullName)(NSString *lastName) = ^(NSString *lName){
        // firstName = @"Jane"; //Variable cannot be assigned here untill and unless the variable is declared as a block type
        return [firstName stringByAppendingFormat:@" %@",lName];
    };
    NSLog(@"Full Name is %@",getFullName(@"Doe"));    //Full Name is John Doe
    
    //Non Local Variables are copied and stored with the blocks are constants (read only)
    //The non local variable cannot be modified
    firstName = @"Jane";
    NSLog(@"Full Name after first name is changed is still %@",getFullName(@"Doe"));
    //Full Name after first name is changed is still John Doe
}

Changing a non local variable within a block

-(void) blocksSampleFive{
    __block NSString *title = @"Mr";
    //The block modifier serves as a memory between multiple calls to a block
    
    NSString *(^getCompleteName)(NSString *name) = ^(NSString *name){
        title = @"Ms"; //If we did not use the block modifier this will continue to hold Mr
        return [title stringByAppendingFormat:@" %@",name];
    };
    NSLog(@"Complete Name is %@",getCompleteName(@"Jane Doe"));
    //Complete Name is Ms Jane Doe
}

Blocks as Method Parameters

-(void)blocksSampleSix{
    NSArray *stringsArray = @[ @"string 1",
                               @"String 21",
                               @"string 12",
                               @"String 11",
                               @"String 02" ];
    
    static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch | NSWidthInsensitiveSearch | NSForcedOrderingSearch;

    NSLocale *currentLocale = [NSLocale currentLocale];
    
    NSComparator finderSortBlock = ^(id string1, id string2) {
        NSRange string1Range = NSMakeRange(0, [string1 length]);
        return [string1 compare:string2 options:comparisonOptions range:string1Range locale:currentLocale];
    };
    
    //In the below line of code the finderSortBlock is sent as a method parameter
    NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];
    NSLog(@"finderSortArray: %@", finderSortArray);
    /*
     Output:
     finderSortArray: (
     "string 1",
     "String 02",
     "String 11",
     "string 12",
     "String 21"
     )
     */
}

Enumerate Objects Using Block

-(void)blocksSampleSeven{
    NSArray *numberArray = @[@12,@13,@10,@9,@100,@109,@432];
    [numberArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"index = %d  value = %d %@",idx,[obj intValue],stop?@"Yes":@"No");
    }];
    //index = 0  value = 12 Yes
    //index = 1  value = 13 Yes
    //index = 2  value = 10 Yes
    //index = 3  value = 9 Yes
    //index = 4  value = 100 Yes
    //index = 5  value = 109 Yes
    //index = 6  value = 432 Yes
}

A simple block that simply executes without taking any input parameter or returning any value

-(void)blocksSampleEight
{
    void (^callSimpleBlock)(void) = ^{
        NSLog(@"This is a block, Takes nothing, gives nothing");
    };
    callSimpleBlock();
}

Test Block to find the index of objects in an array present in a NSSet

-(void)testSetAndArrays{
    NSArray *array = @[@"A", @"B", @"C", @"A", @"B", @"Z", @"G", @"are", @"Q"];
    NSSet *filterSet = [NSSet setWithObjects: @"A", @"Z", @"Q", nil];

    BOOL (^test)(id obj, NSUInteger idx, BOOL *stop);
    test = ^(id obj, NSUInteger idx, BOOL *stop) {
        if (idx < 5) {
            if ([filterSet containsObject: obj]) {
                return YES;
            }
        }
        return NO;
    };
    NSIndexSet *indexes = [array indexesOfObjectsPassingTest:test];
    NSLog(@"indexes: %@", indexes);
    //indexes: [number of indexes: 2 (in 2 ranges), indexes: (0 3)]
}

 Block Completion- Sample 1

-(void)blocksSampleNine{
    [self doSomething:^{
        NSLog(@"This is the completion block. This will get called after the job at doSomething is completed");
    }];
}

typedef void (^EndBlock)();

// A method that returns a completion block
-(void)doSomething:(EndBlock)completionBlock
{
    NSLog(@"Do Something first");
    //This can be a lengthy calculation here.
    //Once this is done then the completion block is called
    
    completionBlock();
    NSLog(@"Then may be something else");
}

 Block Completion- Sample 2

-(void)blocksSampleTen{
    [self countToHundredAndReturnCompletionBLock:^(BOOL completed){
        if(completed)
        {
            NSLog(@"Hundred Counts Finished");
        }
        else
        {
            NSLog(@"Actually Completed but showing not completed. Returning NO here");
        }
    }];

}

// A method that returns a completion block
-(void)countToHundredAndReturnCompletionBLock:(void (^)(BOOL))completed
{
    int x = 1;
    while (x < 100) {
        x++;
    }
    completed(YES);
}

Display Progress Indicator and Hide Progress Indicator in Completion Block

/*
 Using Blocks to Show/hide progress indicator while a task is being executed
 A simple block implementation to show a progress indicator while a task is in progress.
 Once the task is completed the progress indicator needs to hide.
 */

-(void)blocksSampleEleven{
    [self getDataFromDatabase:self];
}

/* The order of execution is as follows
-[AppDelegate getDataFromDatabase:]
-[AppDelegate showProgressIndicator]
-[AppDelegate doActualDatabringingActivity:]
-[AppDelegate hideProgressIndicator]
*/
-(IBAction)getDataFromDatabase:(id)sender
{
    NSLog(@"%s",__func__);
    [self showProgressIndicator];
    
    [self doActualDatabringingActivity:^{
        [self hideProgressIndicator];
        /*
         Avoid Strong reference cycles when capturing self inside blocks
         Capturing a strong reference to self creates a strong reference cycle.
         //To avoid this, its better to capture a wek reference to self
         
         InterfaceName *__weak weakSelf = self;
         [weakSelf doSomething];
         */
    }];
}

-(void)doActualDatabringingActivity:(void (^) (void))callBackBlock
{
    NSLog(@"%s",__func__);
    callBackBlock();
}

-(void)showProgressIndicator
{
    NSLog(@"%s",__func__);
}

-(void)hideProgressIndicator
{
    NSLog(@"%s",__func__);
}

Get Data from WebService / Database using Blocks

-(void)findDataFromWebService{
    [[SampleService sharedInstance] fetchCompanyDataWithCompletionBlock:^(NSDictionary *companyRecord, NSError *error) {
        if (!error) {
            NSLog(@"companyRecord %@",companyRecord);
        }
        else
        {
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                [NSApp presentError:error];
            }];
        }
    }];
}
@end
#import <Foundation/Foundation.h>
@interface SampleService : NSObject

+(SampleService *)sharedInstance;
-(void) fetchCompanyDataWithCompletionBlock:(void(^)(NSDictionary *companyRecord, NSError *error)) completionBlock;
@end

//  SampleService.m
//  ObjcBlocks
//  Created by Debasis Das on 4/19/15.

#import "SampleService.h"
@implementation SampleService

+(SampleService *) sharedInstance
{
    static SampleService *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[SampleService alloc] init];
    });
    return _sharedInstance;
}

-(void) fetchCompanyDataWithCompletionBlock:(void(^)(NSDictionary *companyRecord, NSError *error)) completionBlock
{
    //Create a service request
    //Post the service request
    //Actual Data receiveing goes here
    NSDictionary *companyRecord = [NSDictionary dictionaryWithObjectsAndKeys:@"1000",@"companyId", nil];
   // NSError *error = nil;
    NSError *error = [NSError errorWithDomain:@"Database Connection probably failed" code:7654310 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Some Error Desc",@"errorDesc", nil]];
    completionBlock (companyRecord, error);
}

Download the Source code from ObjcBlocks

Posted in Cocoa, Objective C Tagged with: , ,
5 comments on “Objective C Blocks Sample Code
  1. Imran Khan says:

    Hi … Great Tutorial for beginners..

    • Imran Khan says:

      Hi If u could elaborate why we are going to use shared instance. how it is useful. That would be good to understand end to end. Thanks

      • Debasis Das says:

        Hi Imran,

        The sample service class is a singleton and thus the sharedInstance.
        The only objective of the SampleService class is to get data from the db through a webservice. We can create a SampleService as subclass of NSObject and do not make it a singleton and still things will work, however everytime we need to call the fetchCompanyDataWithCompletionBlock we have to create an object of SampleService.

        I am writing another article to fetch data from webservice using two different approaches. (Call Back vs NSURLSession Delegate). Once you go through this new article, I think things will be much more clearer.

        Thanks
        Debasis

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Recent Posts


Hit Counter provided by technology news