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.
__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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With