Search code examples
iosobjective-cblock

Should I use function parameters in block, or keep them as __block variables


When I use a instance variable inside a block, the best practice is to add __block before it, so the scope is async, and I will be able to use it after. Example:

-(void) someFunction {

    __block NSString *nameIWillUseInBlock = @"Some name"; //Here ill use the __block

    [self functionWithCallback:^(NSString *string) {

        NSString *stringWithString = [NSString stringWithFormat:@"%@%@", nameIWillUseInBlock, @"with bla"];

        //Here Ill do somthing with this string
    }];
} 

So my question is, what about params passed to the function, can I use them like so:

-(void) someFunctionWithParam:(NSString *) nameIWillUseInBlock {

    [self functionWithCallback:^(NSString *string) {

        NSString *stringWithString = [NSString stringWithFormat:@"%@%@", nameIWillUseInBlock, @"with bla"];

        //Here Ill do somthing with this string
    }];
}

Or should I keep the param as a __block instance like so:

-(void) someFunctionWithParam:(NSString *) nameIWillUseInBlock {

    __block NSString *asyncNameIWillUseInBlock = nameIWillUseInBlock;

    [self functionWithCallback:^(NSString *string) {

        NSString *stringWithString = [NSString stringWithFormat:@"%@%@", asyncNameIWillUseInBlock, @"with bla"];

        //Here Ill do somthing with this string
    }];
}

And if I should use the params, and not as a __block instance, how does the scope know witch params did pass before the current scope?

Thanks.


Solution

  • Here is a really good apple doc on the topic Working With Blocks I think the section "Blocks Can Capture Values from the Enclosing Scope" is what you are looking for specifically.

    "In this example, anInteger is declared outside of the block, but the value is captured when the block is defined.

    Only the value is captured, unless you specify otherwise. This means that if you change the external value of the variable between the time you define the block and the time it’s invoked"

    So if you look at this:

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

    The log will show

    Integer is: 42
    

    "Use __block Variables to Share Storage"

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

    The log will show

    Integer is: 84