块中的强引用,会保留吗?

Qua*_*Dam 3 objective-c objective-c-blocks

我从公司的文档中发现了这个代码段:

__weak __typeof(self)weakSelf = self;
dispatch_async(dispatch_get_main_queue(),
^{
      __strong __typeof(weakSelf)strongSelf = weakSelf; 
      // Do stuff
});
Run Code Online (Sandbox Code Playgroud)

它会被保留吗?

Avi*_*Avi 7

捕获weak块内引用有两个原因.

  1. 避免保留周期

  2. 创造无操作的情况.

前者已被讨论过令人作呕.第二个更有趣.

有问题的块是图像下载的完成处理程序.下载完成后,将在图像视图中显示.

如果图像视图已被解除分配(例如用户已切换到新视图),则无需执行任何操作.没有保留周期的危险,因为图像视图没有对块的引用.但是,捕获weak引用允许在块执行之前取消分配图像视图.因此,如果用户在下载图像之前切换视图,则该块最终不执行任何操作,因为其weak参考已被nil编辑.如果图像视图在块的执行过程中被解除分配也无关紧要,因为它只是将图像视图上的操作转换为无操作,而不是将整个块转换为无操作.

但是,有时块会想要无操作行为,但只有当引用已经nil开始时(或者到达代码路径中的某个点)时才会出现.如果在块执行时对象是活动的,则块必须完整地执行.它无法中途停止,因为该对象在其他某个线程上被释放.

完成块的目的是将由字符串定义的标题添加到图像.如果已经取消分配字符串,则不添加标题.但是,如果字符串在后处理开始时仍处于活动状态,则必须保持活动状态以避免尝试使用nil引用创建属性字符串,因为这会导致崩溃.

在这种情况下,使用weak引用捕获字符串是正确的,因此可以通过其他一些线程释放它(导致没有标题).但是,在块中使用字符串之前,必须捕获它strong以避免在创建属性字符串时发生崩溃.

  • 嘿-这很烦我,所以我问了一个在iOS上为Apple工作的朋友。简短的答案是,您是对的。我们使用weakSelf来避免循环,而使用强副本来防止在执行块期间释放。但是,何时需要这种方法的清单非常晦涩:(a)带有块的保留周期(罕见),(b)在不确定的情况下释放self的多线程使用self(ra),(c)代码在不止一次提到自我指针的代码块中,(d)在没有nil-ed有害的情况下使用自我指针(非常罕见)。a * b * c * d =稀有。(继续...) (2认同)