我已经阅读了关于强/弱self
的帖子来打破保留周期,但我仍然对它们是如何工作感到困惑。我理解使用__weak typeof(self) weakSelf = self
创建一个弱的自我引用,但我对强引用感到困惑。据我所知,强引用是为了强烈引用self
,以便它不会在块结束之前解除分配?那么为什么有必要有__strong typeof(self) strongSelf = weakSelf
?这最终是否指向自我对象?那么为什么不只是strongSelf = self
?
在块中引用的任何非弱对象都将导致在创建块时对该对象进行隐式保留。没有执行,但已创建。
如果您直接从self初始化内部strongSelf,您将保留self的值并可能导致保留周期。
另一方面,如果从weakSelf初始化它,则不会保留weakSelf的值。
这就是两步的原因。外部代码将self的值复制到weakSelf中,但ARC不会添加retain,因为它是__weak()。
块“创建”复制weakSelf的值(或者至少设法在执行时使其值可用)。你无法看到它复制到哪里,但确实如此。
在块“执行”时,块复制“weakSelf的值”(如果self已经被平均释放,则为nil)为strongSelf,然后ARC将保留应用于。因此,对于块的持续时间,strongSelf引用的对象将保持活动状态,如果它始终处于活动状态。如果你只依赖于weakSelf,那么在执行块期间它可能会随时变为零。
注意弱/强模式是带括号 - 许多例子实际上依赖于weakSelf将为零的事实,并且该块将默默地成为无操作的集合(消息为零)。
保留周期通常只发生在以下情况下:(a)您在self.property中保留对块的引用;或者(b)将块移交给其他对象(通知管理器等),并告诉其他对象忘记它你的dealloc;在这两种情况下,当块处于活动状态时,永远不会调用dealloc。
当人们说“做这些事情的方式是弱势/强势模式”时,他们会假设最糟糕的情况。
模式是:
__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
的目的。
有正确的答案,但我真的不知道,他们是否是你的Q的答案。他们解释了使用自我一般的块保留周期的问题,但你的Q是:
那么为什么不只是强自我=自我?
这个Q的答案:
如果有人这样做,self
将成为该区块关闭的一部分并始终保留。自我弱的整个故事将毫无意义。
简单来说
__weak typeof(self)weakSelf = self - 我们在块之前使用它,
这只是指向self的指针,没有保留循环开始
- 当且仅当块将执行时才会保留
- >如果我们使它变强,那么即使我们不调用块,它也会开始保留周期并消耗内存
必须清除一点,你没有使用弱/强模式来避免保留周期!无论你是强烈引用自我还是弱自己,你都不会避免保留周期。保留周期被参考变量范围打破!当它到达范围的末尾时,将释放引用变量。弱/强模式只是一种保护机制,阻止你强制引用nil,因为在创建和运行块之前,self可能会被释放。