9

这个问题引用了这个问题: 如何使用块简化回调逻辑?

我的标题有这些 typedef

typedef void (^StuffDoneBlock)(NSDictionary * parsedData);
typedef void (^StuffFailedBlock)(NSError * error);

并在初始化

stuffDoneCallback = Block_copy(done);
StuffFailedCallback = Block_copy(error);

在本文中,它说 Block_copy 是不必要的。但是它需要一个桥接演员表。编译器消息如下:

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__)))
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
4

1 回答 1

22

首先,你为什么还要使用Block_copy()?除非您正在编写原始 C,否则您应该-copy改为调用该块,如[done copy]. 其次,ARC 将为您复制需要超出其初始化范围[1] 的块,因此您甚至不需要再调用-copy。唯一的“例外”是块类型的属性仍然需要具有copy属性。

[1]:这里似乎需要澄清。ARC 仅在编译器发现它需要超出其初始化范围时才隐式复制块。这基本上意味着当它被分配给一个脱离当前范围的变量(在父范围中声明的堆栈变量、实例变量、静态等)时。但是,如果它作为参数传递给方法/函数,编译器不会进行任何自动复制。通常这不是问题,因为需要在堆栈帧(dispatch_async()、完成块等)之后保留块的块感知方法/函数将为您复制它们。但是,支持块的 API(例如NSArray)不会隐式复制块,因为它们期望一个简单的-retain会成功的。如果您将块传递给非块感知 API,并且块需要超出当前范围,则必须使用显式-copy.

于 2011-10-11T21:09:04.480 回答