Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: method returns a block then the block is stored in array, when should I copy it?

I have a method that returns a block and another method which uses the method:

- (MyBlock)blockForParameter:(id)param
{
    MyBlock theBlock = ^(){NSLog(@"Param: %@", param);};
    return theBlock;
}

- (void)methodUser
{
    MyBlock theBlock = [self blockForParameter:something];
    [self.allBlocks addObject:theBlock];
}

The question is, when should I copy the block? Should I copy the block when I return it in blockForParameter, or should I copy it when I add it to the array?

Thanks

like image 881
hzxu Avatar asked Oct 04 '22 16:10

hzxu


2 Answers

Blocks must be copied if they "outlive the scope in which they were created", so you must copy the block in your blockForParameter method, before returning it.

Edit: With ARC, this is no longer true. See for example Objective-C: blocks in ARC and the references therein:

  • Returning a block from a function does not require to copy the block.
  • Adding a block to a collection does require a block copy.
like image 53
Martin R Avatar answered Nov 13 '22 16:11

Martin R


Look at each method separately.

In -blockForParameter:, the block literal is returned from the method. The block must be copied in order to outlive the scope of the literal. In MRC, you would need to return the block copied and autoreleased. In ARC, you don't need to do anything.

In -methodUser, the block is not defined in that method; it is received from a method call. Thus, it must have already been copied (i.e. it is not a stack block). Thus, you do not need to do anything with it when you do addObject: to it.

like image 22
newacct Avatar answered Nov 13 '22 18:11

newacct