In ARC, you no longer need to manually copy blocks in this case or in most others. According to clang ARC block documentation
With the exception of saving the __strong parameter as part of the initialization of the variable or reading the __weak variable, whenever these semantics require saving the value of the type of the block pointer, it has the Block_copy effect. The optimizer can delete such copies when it sees that the result is used only as an argument to the call.
In other words, most of the time saving a block has the Block_copy effect , as you expected, it should be like that. In particular, when a block is added to the collection, it is copied! (More precisely, it is already on the heap.) Here is an example code that shows that it is.
#import <Foundation/Foundation.h> int main(int argc, char *argv[]) { @autoreleasepool { NSMutableArray *arr = [[NSMutableArray alloc] init]; int counter = 0; int total = 5; for (int i = 0; i < total; i++) { void (^block)(void) = ^{ NSLog(@"in this block, counter is %d", counter); }; [arr addObject:block]; counter += 1; } for (int i = 0; i < total; i++) { void (^block)(void) = arr[i]; block(); } } }
If you use the latest Xcode (4.6.3 (4H1503)) with the default compiler (Apple LLVM 4.2 compiler), then this will be
in this block, counter is 0 in this block, counter is 1 in this block, counter is 2 in this block, counter is 3 in this block, counter is 4
If these blocks were not copied to the heap, you (probably this behavior is undefined) see
in this block, counter is 4 in this block, counter is 4 in this block, counter is 4 in this block, counter is 4 in this block, counter is 4
since the pointers added to the array all pointed to the allocated stack (not copied) block, which - during the execution of the blocks - fixed the value counter 4 .
In particular, this is the same behavior that you get if you disable ARC. Even if you call retain on blocks before adding them to the array
[arr addObject:[block retain]]
you will still get the same ("broken") output illustrating that this is ARC behavior, not saving behavior at all .
Note:
In two places where saving ARC does not affect Block_copy,
(1) saved as part of initializing the __strong parameter __strong
Immediately after entering a function (or method), if an object is passed to this function (or method), this object will be saved (there is a strong reference to the object in the stack frame) and will be released when the function (or method) (significant reference to the object is freed )
This is as true for blocks as it is for any other object. This phrase in the clang documentation means that although the block is saved in this case, the block will not be copied by this save.
(2) saved as part of reading __weak variable
Similarly, when the __weak variable __weak read into the __strong variable, a strong reference to the object is created and the object is saved.
This also applies to blocks. Blocks that are sent are saved this way (as a result of reading the __weak link to the __strong link), however, they are not copied.
Cases where one of these two exceptions cause problems are rare. In general, you do not need to worry about copying your blocks.