简体   繁体   English

用强弱自我打破保留周期

[英]Breaking retain cycle with strong/weak self

I've read posts about strong/weak self to break retain cycles but I am still confused as to how they work. 我已经阅读了关于强弱/弱self帖子来打破保留周期,但我仍然对它们是如何工作感到困惑。 I understand the use of __weak typeof(self) weakSelf = self to create a weak reference to self but I am confused about strong reference. 我理解使用__weak typeof(self) weakSelf = self来创建一个弱的自我引用,但我对强引用感到困惑。 As I understand it, the strong reference is so that there is a strong reference to self so that it doesn't get deallocated before the end of the block right? 据我所知,强引用是有一个强烈的self引用,以便它不会在块结束之前解除分配吗? So why is it necessary to have __strong typeof(self) strongSelf = weakSelf ? 那么为什么有必要让__strong typeof(self) strongSelf = weakSelf Doesn't this end up pointing to the self object anyway? 这最终是否指向自我对象? So why not just strongSelf = self ? 那么为什么不只是strongSelf = self

Any non-weak object that you reference inside the block will result in an implicit retain on that object, as the block is being created. 在块中引用的任何非弱对象都将导致在创建块时对该对象进行隐式保留。 Not executed, but created. 没有执行,但已创建。

If you initialised the inner strongSelf directly from self, you will retain the value of self and potentially cause a retain cycle. 如果您直接从self初始化内部strongSelf,您将保留self的值并可能导致保留周期。

On the other hand, if you initialise it from weakSelf, you will not retain the value of weakSelf. 另一方面,如果从weakSelf初始化它,则不会保留weakSelf的值。

This is the reason for the two-step. 这就是两步的原因。 The outer code copies the value of self into weakSelf, but ARC does not add a retain because it is __weak(). 外部代码将self的值复制到weakSelf中,但ARC不会添加retain,因为它是__weak()。

The block "creation" copies the value of weakSelf (or at least, manages to makes its value available at execution time). 块“创建”复制weakSelf的值(或者至少设法在执行时使其值可用)。 You can't see where it copied it to, but it did. 你无法看到它复制到哪里,但确实如此。

At block "execution" time, the block copies the "value of weakSelf" (which will be nil if self has been dealloc'ed in the mean time) into strongSelf which ARC then applies a retain to. 在块“执行”时,块复制“weakSelf的值”(如果self已经被平均释放,则为nil)为strongSelf,然后ARC将保留应用于。 Thus, for the duration of the block, the object referenced by strongSelf will remain alive, if it was alive to begin with. 因此,对于块的持续时间,strongSelf引用的对象将保持活动状态,如果它始终处于活动状态。 If you had only relied on weakSelf, it could go nil at any time during the execution of the block. 如果你只依赖于weakSelf,那么在执行块期间它可能会随时变为零。

Note that weak/strong pattern is belt-and-braces - many examples actually rely on the fact that the weakSelf will go nil, and the block will silently become a collection of no-ops (messages to nil). 注意弱/强模式是带括号 - 许多例子实际上依赖于weakSelf将为零的事实,并且该块将默默地成为无操作的集合(消息为零)。

Retain cycles typically only occur if (a) you keep a reference to the block in a self.property or (b) you hand the block off to some other object (notification manager, etc), and tell that other object to forget it in your dealloc; 保留周期通常只发生在以下情况下:(a)您在self.property中保留对块的引用;或者(b)将块移交给其他对象(通知管理器等),并告诉其他对象忘记它你的dealloc; in both cases your dealloc will never be called while the block is alive. 在这两种情况下,当块处于活动状态时,永远不会调用dealloc。

When people say "the way to do this stuff is with the weak/strong pattern", they are assuming the worst possible scenario. 当人们说“做这些事情的方式是弱势/强势模式”时,他们会假设最糟糕的情况。

The pattern is: 模式是:

__weak typeof(self) weakSelf = self;

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

The idea is that the completion handler block will have only a weak reference to self , so that if self is released before the completion block is called, then it will safely be deallocated because the block has no strong reference to it. 这个想法是完成处理程序块只有一个对self的弱引用,因此如果在调用完成块之前释放self ,那么它将被安全地释放,因为该块没有强引用。 (A common example is when a view controller initiates some asynchronous network request to update a view, if the view controller is dismissed before the network request finishes, there's no point on hanging onto the view controller instance for a view that is long gone.) (一个常见的例子是,当视图控制器发起一些异步网络请求来更新视图时,如果视图控制器在网络请求完成之前被解除,那么对于一个早已消失的视图,没有必要挂在视图控制器实例上。)

But, this weakSelf / strongSelf pattern also ensures that if the opposite happens, that the completion block has started and encounters the strongSelf line before self is released, the block will ensure that self is retained for the duration of the running of that block (ie it can't get deallocated half way through the running of the completion block, even if this is running on a different thread). 但是,这个weakSelf / strongSelf模式还确保如果相反的情况发生,即完成块已经启动并且在self释放之前遇到strongSelf线,则该块将确保在该块的运行期间保留self (即它不能在完成块的运行中途被解除分配,即使它在不同的线程上运行)。 This has a number of potential benefits (ranging from object integrity to the elimination of race conditions). 这具有许多潜在的好处(从对象完整性到消除竞争条件)。 Sometimes you don't actually need the strongSelf half of the " weakSelf / strongSelf dance", but it's an invaluable tool when needed. 有时你实际上并不需要“ weakSelf / strongSelf舞蹈”的strongSelf一半,但它在需要时是一个非常宝贵的工具。

If, however, you had a line inside the block that said, typeof(self) strongSelf = self (instead of weakSelf ), the mere presence of self in the righthand side of that statement would result in the block maintaining a strong reference to self up front, entirely defeating the purpose of using weakSelf in the first place. 但是,如果你在块中有一行说明, typeof(self) strongSelf = self (而不是weakSelf ),那么在该语句的右侧仅仅存在self将导致该块保持强烈的self引用在前面,完全打败了首先使用weakSelf的目的。

There are correct answers, but I really do not know, whether they are answers to your Q. They explain the problem of retain cycles with blocks using self in general, but your Q was: 有正确的答案,但我真的不知道,他们是否是你的Q的答案。他们解释了使用自我一般的块保留周期的问题,但你的Q是:

So why not just strongSelf = self? 那么为什么不只是强自我=自我?

The answer to this Q: 这个Q的答案:

If one would do this, self would be a part of the block's closure and always be retained. 如果有人这样做, self将成为块关闭的一部分并始终保留。 The whole story with weak self would be meaningless. 自我弱的整个故事将毫无意义。

In simple words 简单来说

__weak typeof(self) weakSelf = self - We use this just before block, __weak typeof(self)weakSelf = self - 我们在块之前使用它,

This is just pointer to self, no retain cycle started 这只是指向self的指针,没有保留循环开始

-- Retain will be done if and only if block will execute - 当且仅当块将执行时才会保留

--> If we make it strong then it will start retain cycle and will consume memory, even if we don't call block - >如果我们使它变强,那么即使我们不调用块,它也会开始保留周期并消耗内存

One point must be cleared that you are not using weak/strong pattern to avoid retain cycle! 必须清除一点,你没有使用弱/强模式来避免保留周期! Whether you use a strong reference to self or to weakself, you are not avoiding retain cycle. 无论你是强烈引用自我还是弱自己,你都不会避免保留周期。 Retain cycle is broken by the reference variable scope! 保留周期被参考变量范围打破! When it reached the end of the scope, the reference variable is dealloced. 当它到达范围的末尾时,将释放引用变量。 The weak/strong pattern is just a protection mechanism that prevent you make a strong reference to nil, since before the block is created and run, self maybe dealloced. 弱/强模式只是一种保护机制,阻止你强制引用nil,因为在创建和运行块之前,self可能会被释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM