mariia
2/27/2019 - 3:43 AM

Objective-C blocks types example

Example from Effective Objective-C 2.0 book (chapter 6, blocks).

typedef int(^MySuperBlock)(BOOL success, int result);

@interface MyClass : NSObject 

@property (nonatomic, strong) NSString *name; 

@end 

@implementation MyClass

- (void)exploringTypedef {
    MySuperBlock block = ^(BOOL success, int result){
        //TODO: implement. 
    };
}

- (void)ivarCaptureExample {
    //Blocks are objects. 
    void (^processBlock)() = ^{
        //Is equivalent to self->_name = @"New name", so 'self' is captured by processBlock.
        _name = @"New name";
        NSLog(@"Please welcome %@", _name);
    };
}

/*
    Blocks are exist only inside the scope they allocated in (because blocks allocate 
    the region of memory on the stack). 
*/
- (void)blockScopeIssueExample {
    void (^block)();

    if (/* some condition */) {
        //This block is guaranteed to be valid only in this 'if' section. 
        block = ^{
            NSLog(@"Hello world!");
        }; //compiler can override memory where block is stored right after going out of this scope.
    } else {
        block = ^{
            NSLog(@"Bye world!");
        }; //same problem here. 
    }

    block();
}

- (void)blockScopeIssueFixExample {
    void (^block)();

    if (/* some condition */) {
        //By sending 'copy' to block, it is copied from stack to heap and become a ARC-object.
        //It will support reference counter.
        //Otherwise while it is on stack it is cleaned automatically at the end of the scope.
        block = [^{
            NSLog(@"Hello world!");
        } copy];
    } else {
        block = [^{
            NSLog(@"Bye world!");
        } copy];
    }

    block();
}

/*
    Global block.
    It is allocated in global memory and will never be released. 
    This kind of blocks can't capture any state, such as variables. 
*/
void (^block)() = ^{
    NSLog(@"This is a block");
};

@end