如何使用ARC释放块

Ser*_*nko 0 objective-c ios objective-c-blocks

说明:

我将块传递给异步方法,并在操作完成时调用它.我想在操作完成之前拒绝调用块.但是如果我将nil分配给我的类中的块变量,那么无论如何都要调用它.我调试了它,我看到如果我将nil分配给块变量1,则变量2不是nil.下面的代码说明了这一点:

void (^d1)(NSArray *data) = ^(NSArray *data) {};

void (__weak^d2)(NSArray *data) = d1;

d1 = nil;
Run Code Online (Sandbox Code Playgroud)

输出:

(lldb) po d1
<__NSGlobalBlock__: 0x9c22b8>]
(lldb) po d2
<__NSGlobalBlock__: 0x9c22b8>
(lldb) po d1
<nil>
(lldb) po d2
<__NSGlobalBlock__: 0x9c22b8>
Run Code Online (Sandbox Code Playgroud)

问题:

为什么阻止d2不是零?是按值复制而不是复制为指针?

new*_*cct 5

首先,您永远不应该依赖于在特定位置释放的对象.其他人(例如自动释放池)总是可以在您不知情的情况下持有对它的引用.对象不能在任何地方解除分配是不正确的.

好的,就你的情况而言:__NSGlobalBlock__给出一个提示:这是一个"全局块".在块的当前实现中,有3种类型的块对象:stack blocks(__NSStackBlock__),heap blocks(__NSMallocBlock__)和global blocks(__NSGlobalBlock__).

作为闭包的块(即使用来自外部作用域的一些局部变量)从"堆栈块"开始 - 对象结构具有自动存储持续时间,就像局部变量一样,当它离开定义的范围时它变得无效当堆栈块被"复制"时,它将被移动到堆上动态分配的对象,就像Objective-C中的所有其他对象一样.这是一个堆块.它与Cocoa中的其他对象一样被引用计数,并且复制它与retain具有相同的效果.

闭包的块(这是您的示例中的块)被实现为"全局块".因为它不包含任何捕获的变量,所以块的所有实例都是相同的,因此在整个程序中只有一个实例.它像字符串文字一样静态分配,并且在程序的整个生命周期中都存在.它不是引用计数,保留,释放和复制它不起作用.它不能被解除分配; 这就是为什么你的弱引用永远不会被设置为nil.一个__weak参考之用被设定为nil如果它指向的对象,以被释放.