[英]Are there potential drawbacks to using a [weak self] within a closure after declaring a strong self?
The title I used for this may not be particularly clear, so I hope that a working code sample can provide some clarity.我为此使用的标题可能不是特别清楚,所以我希望一个工作代码示例可以提供一些清晰度。
The issue I am facing is that I have a scenario similar to the code below:我面临的问题是我有一个类似于以下代码的场景:
import Foundation
class Test {
private var isInner = false {
didSet {
print("isInner: \(isInner)")
}
}
private func runClosure(closure: () -> ()) {
closure()
}
func callClosure() {
// Weak 1
runClosure { [weak self] in
self?.isInner = false
guard let strongSelf = self else { return }
// Can this [weak self] create problems?
// Weak 2
strongSelf.runClosure { [weak self] in
self?.isInner = true
}
}
}
}
let test = Test()
test.callClosure()
// The following is printed to the console
// isInner: false
// isInner: true
Everything above works precisely as intended, which is good.上面的一切都按预期工作,这很好。
My concern is the second use of [weak self]
.我关心的是
[weak self]
的第二次使用。 While self
is declared weak at the start of the function ( Weak1 ), I then set it to strongSelf
shortly thereafter.虽然
self
在函数开始时被声明为弱 ( Weak1 ),但我随后不久将其设置为strongSelf
。
I could re-use my earlier strongSelf
, but the functions in question are actually potentially long running operations and there exists the possibility that self could be out of scope between Weak1 and Weak2 .我可以重用我之前的
strongSelf
,但有问题的函数实际上可能是长时间运行的操作,并且存在 self 可能超出Weak1和Weak2范围的可能性。
However, it has been brought to my attention that the potential exists for Weak2
to be invalid, which is what I am hoping to clarify with this question.但是,我注意到
Weak2
存在无效的可能性,这就是我希望通过这个问题澄清的。
Ultimately, all that weak does is create an optional variable for self, so I am not aware of any potential pitfalls.最终,weak 所做的只是为 self 创建一个可选变量,所以我不知道任何潜在的陷阱。 Additionally, Weakself1 ,
strongSelf
, and Weakself2 are all pointing at the same memory address during the execution of callClosure()
.此外,在
callClosure()
执行期间, Weakself1 、 strongSelf
和Weakself2都指向相同的内存地址。
Let's take this step by step (line by line)让我们一步一步来(一行一行)
// Weak 1
runClosure { [weak self] in
The first line creates a reference to the target object, a reference which coincidentally (or not) is named self
.第一行创建了对目标对象的引用,该引用巧合(或不巧合)命名为
self
。
self?.isInner = false
The above line makes use of the weak reference, it has no effects on the target object lifecycle.上面这行使用了弱引用,它对目标对象生命周期没有影响。
guard let strongSelf = self else { return }
Now, this line indeed creates a strong reference to the target object, which will extend objects's lifetime by at least the lifetime of strongSelf
.现在,这一行确实创建了对目标对象的强引用,这将对象的生命周期至少延长
strongSelf
的生命周期。 Now depending on the compiler aggressiveness, strongSelf
might die after passing this line (the last reference in code), or when the outer closure finishes executing.现在,根据编译器的积极性,
strongSelf
可能会在传递此行(代码中的最后一个引用)后或在外部闭包完成执行后死亡。
// Can this [weak self] create problems?
// Weak 2
strongSelf.runClosure { [weak self] in
Now this has almost exactly the same effect as the capture from the outer closure.现在这与从外部闭包捕获的效果几乎完全相同。 It creates a reference to a possibly already deallocated instance (depending if
strongSelf
is still alive at this point or not).它创建一个对可能已经释放的实例的引用(取决于
strongSelf
是否还活着)。
self?.isInner = true
This is the regular optional usage, no effects on target lifetime.这是常规的可选用法,对目标寿命没有影响。
Now, assuming that runClosure
runs asynchronously, there are no issues with the target object living more that expected (assuming there aren't any more strong references out there).现在,假设
runClosure
异步运行,目标对象比预期的更runClosure
(假设那里没有runClosure
没有问题。
To summarize, an object lifetime is determined by the number of strong references exist to that object.总而言之,对象生命周期由对该对象存在的强引用的数量决定。 Once all strong references are destroyed, the object will be automatically deallocated.
一旦所有强引用都被销毁,对象将被自动释放。 In your particular scenario, the inner closure weakly captures and already weak reference, and this doesn't impact the lifecycle of the target object.
在您的特定场景中,内部闭包弱捕获并且已经弱引用,这不会影响目标对象的生命周期。 The only player is
strongSelf
, which gets destroyed no later than the outer closure destroyal.唯一的玩家是
strongSelf
,它在不迟于外部闭包销毁之前被销毁。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.