This Question references this Question:
How to simplify callback logic with a Block?
My header has these typedefs
typedef void (^StuffDoneBlock)(NSDictionary * parsedData);
typedef void (^StuffFailedBlock)(NSError * error);
And in init
stuffDoneCallback = Block_copy(done);
StuffFailedCallback = Block_copy(error);
In this paper its says that Block_copy is unnecessary. But then it needs a bridged cast.
The compiler message is at follows:
error: cast of block pointer type 'StuffDoneBlock' (aka 'void (^)(NSDictionary *__strong)') to C pointer type 'const void *' requires a bridged cast [4]
stuffDoneCallback = _bridge(Block_copy(done));
^~~~~~~~~~~~~~~~
/Developer-4.2/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/usr/include/Block.h:60:61: note: instantiated from:
#define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
^~~~~~~~~~~~~~~~~~~~~~~~~~~
First off, why are you even using Block_copy()
? Unless you're writing raw C, you should be calling -copy
on the block instead, as in [done copy]
. Secondly, ARC will copy blocks for you that need to live past their initialization scope[1], so you don't need to even call -copy
anymore. The only "exception" is that block-typed properties still need to have the copy
attribute.
[1]: Clarification appears to be needed here. ARC only implicitly copies blocks when the compiler sees that it needs to live past its initialization scope. This basically means when it's assigned to a variable that escapes the current scope (stack variable declared in a parent scope, instance variable, static, etc.). However, if it's passed as an argument to a method/function, the compiler does not do any automatic copying. Typically this isn't a problem because block-aware methods/functions that need to hold onto the block past the stack frame (dispatch_async()
, completion blocks, etc.) will copy them for you. However, APIs that are not block-aware (such as NSArray
) will not implicitly copy the block, since they expect that a simple -retain
will do the trick. If you're passing your block to a non-block-aware API and the block needs to live past the current scope, you must use an explicit -copy
.