You must copy the blocks before passing them to the method, when 1) the block will be stored longer than the duration of the call, and 2) the parameter with which you pass it is the usual type of object pointer (i.e. id or NSObject * ) instead of the block type .
This applies to your call. dictionaryWithObjectsAndKeys: stores the argument in the resulting dictionary and simply expects the usual arguments to the object pointer (of type id ) and does not know if you are passing blocks or not.
The reason for the second condition that I talked about is that if the method parameter already accepts a block type (for example, for any parameters of the completion handler), then this method already knows about the special requirements for managing block memory, and therefore will take responsibility for copying a block if it needs to be saved. In this case, the caller does not need to worry about it. However, in your case, you pass it to a general method that does not know that it receives the block, and therefore does not know to copy it. Therefore, the caller must do this.
Can someone explain why I should use automatic variables to store blocks before putting them into a dictionary?
About this, for example, your second example works because the latest versions of the ARC compiler are very conservative with respect to blocks and insert copies whenever you assign it to a variable of type block. However, this is not guaranteed by the ARC specification and is not guaranteed to work in the future or in another compiler. You should not rely on this behavior.
source share