Objective-C: blocks in ARC

I'm moving on to ARC (Automatic Reference Counting), and this document really helped: Go to ARC Release Notes . It says:

How do blocks work in ARC?

Blocks "just work" when you push blocks up on the stack in ARC mode, for example, in return. You no longer need to call Block Copy. You still need to use [^ {} copy] when passing the "down" stack to arrayWithObjects: and other methods that save.

Can anyone think a little about this or give an example? I realized that, as a rule, I no longer need to [block a copy], even if the block is used outside the declared area, since ARC will take care of it more smartly now, but I still need to copy it when I want to pass the block to the functions, which will save him. Is it correct?

Actually, I experimented a bit with this, and so far this is normal, even if I pass blocks to arrays without copying, so the question is. Thanks!

+6
source share
1 answer

Consider the problem in terms of MRC (manual reference counting). When you return a stack block from a function, you always need to do this to return a copy of it (usually with [[ copy] autorelease] ). This is because the stack block lifetime is a function call that ends. Therefore, for the returned pointer to point to a valid block after returning, of course, you must return a bunch.

However, what about passing the block as an argument to a function or method. Should you give a copy of it? This is a little trickier. We know that if you need to save a block for later use in a place that will survive the function call (for example, in an instance variable or global variable, etc.), you need to save a copy of the block. But how do we know when this is true (and if it is true, which function (caller / callee) is responsible for copying it)?

As a rule, when you pass it to a function or method whose parameter is of a block type, then you do not need to copy it, because, as a function that takes a block parameter, this function is responsible for copying it if it should save it for future use.

But what about passing a block to a function or method whose parameter is of a non-blocking type (e.g. id )? Then this function does not know that its argument is a block, so it will save the object only if it needs to save it later, and not copy it. In this case, if we know that the function or method will store the object around later (for example, using -[NSMutableArray addObject:] ), we must pass a copy of the block. Should we always transfer a copy? Not necessary. If we know that a function or method will not save the block for later (for example, just printing the object), it is inefficient to make a copy of the block.

In ARC, the compiler tries to do as much as possible for you. Therefore, in the case of returning the stack block (β€œpassing it”), the compiler knows that returning the copy is always correct, so it implicitly does this. This is why you no longer need to do this yourself.

However, to transfer a block to a method or function ("pass it down"), it is not always possible to automatically determine whether copying is required or not, and additional copying may be inefficient, so the compiler does not do everything automatically; and you must understand this programmer.

I noticed that in the latest versions of the compiler, ARC copies blocks in a much larger number of situations, which I thought, therefore, maybe they changed the implementation of ARC to pretty much copy blocks, to make mistakes on the side and they believed that the execution cost not so important. Thus, it is possible that now it will work with the block directly on addObject: without explicit copying. But I believe that this does not always apply to ARC, and there is no guarantee in this language in that language, or that this behavior will remain in the future.

+13
source

All Articles