我已经阅读了关于强/弱 self
的帖子来打破保留周期,但我仍然对它们是如何工作感到困惑 . 我理解使用 __weak typeof(self) weakSelf = self
来创建一个弱的自我引用,但我对强引用感到困惑 . 据我了解,强引用是有一个强烈的引用 self
,以便它不会在块结束之前解除分配?那么为什么有必要 __strong typeof(self) strongSelf = weakSelf
?这最终是否指向自我对象?那么为什么不只是 strongSelf = self
?
5 回答
在块中引用的任何非弱对象都将导致在创建块时对该对象进行隐式保留 . 没有执行,但已创建 .
如果您直接从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 .
当人们说“做这些事情的方式是弱势/强势模式”时,他们会假设最糟糕的情况 .
模式是:
这个想法是完成处理程序块只有一个弱引用
self
,所以如果在调用完成块之前释放self
,那么它将被安全地释放,因为该块没有强引用 . (一个常见的例子是,当视图控制器发起一些异步网络请求来更新视图时,如果视图控制器在网络请求完成之前被解除,那么对于一个早已消失的视图,没有必要挂在视图控制器实例上 . )但是,这
weakSelf
/strongSelf
图案还确保如果发生相反的情况,即在完成块已经开始,并且遇到self
被释放之前strongSelf
线,块将确保self
被保留用于该块的运行的持续时间(即它实际上可能需要“weakSelf
/strongSelf
舞蹈”的一半,但在需要时它是一个非常宝贵的工具 .但是,如果你在块中有一行代表
typeof(self) strongSelf = self
(而不是weakSelf
),那么在该语句的右侧仅仅存在self
会导致该块在前面保持强烈的引用,完全击败了首先使用weakSelf
的目的 .有正确的答案,但我真的不知道,他们是否是你的Q的答案 . 他们解释了使用自我一般的块保留周期的问题,但你的Q是:
这个Q的答案:
如果有人这样做,
self
将成为该块关闭的一部分并始终保留 . 自我弱的整个故事将毫无意义 .简单来说
__weak typeof(self)weakSelf = self - 我们在块之前使用它,
This is just pointer to self, no retain cycle started
当且仅当块将执行时才会保留
必须清除一点,你没有使用弱/强模式来避免保留周期!无论你是强烈引用自我还是弱自己,你不是在避免保留周期 . 保留周期被参考变量范围打破!当它到达范围的末尾时,将释放引用变量 . 弱/强模式只是一种保护机制,阻止你强制引用nil,因为在创建和运行块之前,self可能会被释放 .