Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use __block keyword on object references with ARC [duplicate]

I understand that the __block storage type is needed on scalar variables for the block to see updates to them, but when is it needed on objects? I believe __weak should be used when capturing a self reference to be used within the block, but I don't see when it would be necessary to actually use the __block storage type for ordinary objects.

like image 338
chinabuffet Avatar asked Jul 24 '13 00:07

chinabuffet


1 Answers

__block is needed for scalar variables if you want to change their value with code inside the block. Captured scalars appear as const inside the block and therefore cannot be changed. If you have a pointer to an object, the same distinction applies--the captured pointer itself will be a const pointer and therefore cannot be modified, but the object pointed to can be modified by code inside the block. If you want to change the object pointed to, then the pointer itself must change, and so the pointer must be declared with the __block type. It is never necessary to declare the object itself as __block, but only the pointer to the object, and only if the pointer must be changed.

If you have the right mental model, blocks aren't that confusing. It is important to know that blocks are initially allocated on the stack, and so vanish when the lexical scope is destroyed as the stack frame is popped. If you want the block to hang around past the lifetime of the lexical scope in which the block was created, move it to the heap using Block_copy() or sending it a -copy message. When a block is copied to the heap, all the captured const variables go along, and any objects these const variables point to are retained. When the block is removed from the heap, all objects pointed to by the const variables are released.

__block variables "under the hood" have an extra layer of indirection the compiler uses (and that you don't see) included in the block, so when the block is copied to the heap, so are the captured __block variables, and the invisible pointers are adjusted to point to the new heap location of these __block variables. This means the address of a __block variable can change, so be careful if you use that address. You can also see that a __block variable lives 'outside' the block in some sense, so these variables can be read and modified from code external to the block.

I've been brief, but you can find better explanations here, listed in increasing complexity:

http://ios-blog.co.uk/tutorials/programming-with-blocks-an-overview/

http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

http://www.mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html

like image 142
Fred Avatar answered Nov 15 '22 08:11

Fred