假设在 ARC 下有以下代码,
typedef void (^MyResponseHandler) (NSError *error);
@interface MyClass : NSObject
{
MyResponseHandler _ivarResponseHandler;
}
- (void)myMethod:(MyResponseHandler)responseHandler
{
_ivarResponseHandler = responseHandler;
...
}
问:块在分配给 ivar 时是否会自动复制到堆中?
我之前的问题暗示它在通过@property
分配时被复制。 但是,今天我使用了上面的代码并收到了一个EXC_BAD_ACCESS
,该已通过更改为
_ivarResponseHandler = [responseHandler copy]
.
编辑:我之前的答案可能是错误的。
ARC文档中的一些摘录说:
3. 可保留的对象指针
可保留对象指针(或可保留指针(是可保留对象指针类型(可保留类型(的值。有三种可保留的对象指针类型:
- 块指针(通过将插入符号 (^( 声明符符号应用于函数类型而形成(
4.2. 语义
赋值在计算赋值运算符时发生。语义因限定条件而异:
- 对于__strong对象,首先保留新的 pointee;其次,用原始语义加载左值;第三,使用原始语义将新 pointee 存储到左值中;最后,释放旧的 pointee。这不是以原子方式执行的;必须使用外部同步来确保在面对并发加载和存储时的安全。
4.4.1. 对象
如果使用可保留的对象所有者类型声明对象,但没有显式所有权限定符,则其类型将隐式调整为具有__strong限定符。
7.5. 块
除了作为初始化__strong参数变量或读取__weak变量的一部分完成的保留之外,每当这些语义要求保留块指针类型的值时,它都具有Block_copy的效果。当优化程序看到结果仅用作调用的参数时,它可能会删除此类副本。
所以我认为答案是也许,取决于优化器。
你的问题和解决方案表明我对你另一个问题的回答可能是错误的。我基于clang Objective-C自动引用计数文档第7.5节的最后一段:
我将"这些语义">除了作为初始化
__strong
参数变量或读取__weak
变量的一部分完成的保留之外,每当这些语义要求保留块指针类型的值时,它都会产生Block_copy
的效果。当优化程序看到结果仅用作调用的参数时,它可能会删除此类副本。
表示整个文档,但如果"这些语义"仅指第 7.5 节,则 ARC 仅为块捕获的块插入Block_copy
。