简体   繁体   English

在声明强自我之后在闭包中使用 [弱自我] 是否有潜在的缺点?

[英]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 可能超出Weak1Weak2范围的可能性。

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()执行期间, Weakself1strongSelfWeakself2都指向相同的内存地址。

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.

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