ios - 如何使用 ARC 释放 block

标签 ios objective-c objective-c-blocks

描述:

我将我的 block 传递给异步方法,并在操作完成时调用它。我想拒绝在操作完成之前调用该 block 。但是,如果我将 nil 分配给我类(class)中的 block 变量,它仍然会被调用。我调试了它,我发现如果我将 nil 分配给 block variable1,则 variable2 不是 nil。下面的代码说明了这一点:

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

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

d1 = nil;

输出:

(lldb) po d1
<__NSGlobalBlock__: 0x9c22b8>]
(lldb) po d2
<__NSGlobalBlock__: 0x9c22b8>
(lldb) po d1
<nil>
(lldb) po d2
<__NSGlobalBlock__: 0x9c22b8>

问题:

为什么 block d2 不是零?它是按值复制而不是按指针复制吗?

最佳答案

首先,你永远不应该依赖一个对象在特定的地方被释放。其他人(例如自动释放池)总是有可能在您不知情的情况下持有对它的引用。一个对象在任何地方都没有被释放并没有错。

好的,对于你的情况:__NSGlobalBlock__ 给出了一个提示:这是一个“全局 block ”。目前block的实现中,有3种block对象:栈 block (__NSStackBlock__)、堆 block (__NSMallocBlock__)、全局 block (__NSGlobalBlock__)。

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

不是闭包的 block (这就是您示例中的 block )被实现为“全局 block ”。因为它不包含任何捕获的变量,所以 block 的所有实例都是相同的,因此整个程序中只有它的一个实例。它像字符串文字一样被静态分配,并且在程序的整个生命周期内都存在。它不是引用计数的,对它的保留、释放和复制都没有效果。它不能被释放;这就是为什么您的弱引用永远不会设置为 nil 的原因。 __weak 引用只有在它指向的对象被释放时才会被设置为 nil

关于ios - 如何使用 ARC 释放 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20212167/

相关文章:

objective-c - Block_copy是递归的吗?

ios - UINavigationController pop 重置 Root View Controller 的框架

ios - 如何从swift调用 objective-c 中具有处理程序 block 的函数

ios - JSON 未转换为 NSString

objective-c - 自定义 UITableViewCell + resignFirstResponder

c - ^{ <stmts..> }() 在 C 中是什么意思?

objective-c - 在传递给构造函数的 block 中引用 self

ios - 当用户处于通话状态栏时,导航栏布局出现异常

ios - 如何在iOS中强制将音频输出路由到蓝牙A2DP?

ios - 使用指针设置属性而不是发送对象消息