块指针类型被 ARC 视为可保留的对象指针类型__strong qualifiers
,并且根据文档,此类类型(在没有显式所有权限定符的情况下)被隐式假定为具有:
如果一个对象声明为具有可保留对象所有者类型,但没有显式所有权限定符,则其类型被隐式调整为具有 __strong 限定符。
所以上面的例子等价于
int i = 42;
__strong int (^aBlock)() = ^ {
return i;
};
NSLog(@"Class: %@", [aBlock class]);
该文档还指出:
对于__strong
对象,首先保留新的pointee;其次,左值加载了原始语义;第三,新的指针对象以原始语义存储到左值中;最后,旧指针被释放。
后来_
[...] 当这些语义要求保留块指针类型的值时,它具有 Block_copy [...]
Block_copy
所以是的,ARC会在将块分配给变量时引入调用,因为变量被隐式假定为__strong
-qualified。
跳过分配将使块保留在堆栈上。考虑以下示例:
NSLog(@"Class: %@", [^int{return i;} class]); // => Class: __NSStackBlock__
文档还告诉我们,
当优化器发现结果仅用作调用的参数时,它可能会删除此类副本。
确实如此。正如 Catfish_Man 所提议的,打开优化(在这种情况下通过使用 Release 构建配置)将剥离Block_Copy
调用,将块留在堆栈上。