用强弱自我打破保留周期

时间:2015-07-08 02:22:58

标签: ios objective-c cocoa automatic-ref-counting

我已阅读有关强/弱self的帖子以打破保留周期,但我仍然对它们如何运作感到困惑。我理解使用__weak typeof(self) weakSelf = self来创建对自我的弱引用,但我对强引用感到困惑。据我了解,强引用是有一个强引用self,以便它不会在块结束之前解除分配?那么为什么有必要__strong typeof(self) strongSelf = weakSelf?这最终是否指向自我对象?那么为什么不只是strongSelf = self

5 个答案:

答案 0 :(得分:12)

在块中引用的任何非弱对象都将导致在创建块时对该对象进行隐式保留。没有执行,但已创建。

如果你直接从self中初始化内部strongSelf,你将保留self的值并可能导致保留周期。

另一方面,如果你从weakSelf初始化它,你将保留weakSelf的值。

这就是两步的原因。外部代码将self的值复制到weakSelf中,但ARC不会添加保留,因为它是__weak()。

块"创建"复制weakSelf的值(或者至少,设法在执行时使其值可用)。你无法看到它复制到哪里,但确实如此。

在块"执行"时间,该块复制了weakSelf"的值。 (如果自己同时被解除权利,那将是零)进入strongSelf,然后ARC应用保留。因此,对于块的持续时间,strongSelf引用的对象将保持活动状态,如果它始终处于活动状态。如果你只依赖于weakSelf,那么在执行块期间的任何时候它都可以为零。

请注意弱/强模式是带括号 - 许多例子实际上依赖于weakSelf将为零的事实,并且该块将默默地成为no-ops的集合(消息为nil)。

保留周期通常仅在以下情况下发生:(a)您在self.property中保留对块的引用;或者(b)将块移交给其他对象(通知管理器等),并告诉其他对象在你的dealloc中忘记它;在这两种情况下,当块活着时,你的dealloc永远不会被调用。

当人们说"做这些事情的方式是弱/强模式",他们假设最糟糕的情况。

答案 1 :(得分:10)

模式是:

__weak typeof(self) weakSelf = self;

[manager someAsynchronousMethodWithCompletionHandler:^{
    typeof(self) strongSelf = weakSelf;
    if (strongSelf) {
        ...
    }
}];

这个想法是完成处理程序块只有一个对self的弱引用,所以如果在调用完成块之前释放self,那么它将被安全地释放,因为块没有强烈的参考。 (一个常见的例子是当视图控制器发起一些异步网络请求来更新视图时,如果视图控制器在网络请求完成之前被解除,那么在视图控制器实例上挂起的视图就没有意义了。早已不复存在。)

但是,此weakSelf / strongSelf模式还可确保在相反的情况下,完成块已启动并在释放strongSelf之前遇到self行,该块将确保在该块运行期间保留self(即,即使它在另一个线程上运行,它也无法在完成块运行的一半时解除分配) )。这具有许多潜在的好处(从对象完整性到消除竞争条件)。有时您实际上并不需要strongSelf / weakSelf舞蹈的strongSelf一半,但在需要时它是一个非常宝贵的工具。

但是,如果您在块中有一行说typeof(self) strongSelf = self(而不是weakSelf),那么只会在该声明的右侧出现self在块中保持对self的强烈引用,首先完全违背了使用weakSelf的目的。

答案 2 :(得分:1)

有正确的答案,但我真的不知道,他们是否是你Q的答案。他们解释了一般使用自我的块保留周期的问题,但你的Q是:

  

那么为什么不仅仅是强者自我?

这个Q的答案:

如果有人这样做,self将成为块关闭的一部分并始终保留。弱者自我的整个故事将毫无意义。

答案 3 :(得分:0)

简单来说就是

__ weak typeof(self)weakSelf = self - 我们在阻止之前使用它,

这只是指向self的指针,没有启动保留周期

- 当且仅当块执行

时才会保留

- >如果我们强大,那么它将开始保留周期并消耗内存,即使我们不调用块

答案 4 :(得分:0)

必须清除一点,即您没有使用弱/强模式来避免保留周期!无论你是强烈引用自我还是弱自己,你都不会避免保留周期。保留周期被参考变量范围打破!当它到达范围的末尾时,将释放引用变量。弱/强模式只是一种保护机制,阻止你强制引用nil,因为在创建和运行块之前,self可能会被释放。