繁体   English   中英

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

[英]Are there potential drawbacks to using a [weak self] within a closure after declaring a strong self?

我为此使用的标题可能不是特别清楚,所以我希望一个工作代码示例可以提供一些清晰度。

我面临的问题是我有一个类似于以下代码的场景:

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

上面的一切都按预期工作,这很好。

我关心的是[weak self]的第二次使用。 虽然self在函数开始时被声明为弱 ( Weak1 ),但我随后不久将其设置为strongSelf

我可以重用我之前的strongSelf ,但有问题的函数实际上可能是长时间运行的操作,并且存在 self 可能超出Weak1Weak2范围的可能性。

但是,我注意到Weak2存在无效的可能性,这就是我希望通过这个问题澄清的。

最终,weak 所做的只是为 self 创建一个可选变量,所以我不知道任何潜在的陷阱。 此外,在callClosure()执行期间, Weakself1strongSelfWeakself2都指向相同的内存地址。

让我们一步一步来(一行一行)

// Weak 1
runClosure { [weak self] in

第一行创建了对目标对象的引用,该引用巧合(或不巧合)命名为self

    self?.isInner = false

上面这行使用了弱引用,它对目标对象生命周期没有影响。

    guard let strongSelf = self else { return }

现在,这一行确实创建了对目标对象的强引用,这将对象的生命周期至少延长strongSelf的生命周期。 现在,根据编译器的积极性, strongSelf可能会在传递此行(代码中的最后一个引用)后或在外部闭包完成执行后死亡。

    // Can this [weak self] create problems?
    // Weak 2
    strongSelf.runClosure { [weak self] in

现在这与从外部闭包捕获的效果几乎完全相同。 它创建一个对可能已经释放的实例的引用(取决于strongSelf是否还活着)。

            self?.isInner = true

这是常规的可选用法,对目标寿命没有影响。

现在,假设runClosure异步运行,目标对象比预期的更runClosure (假设那里没有runClosure没有问题。

总而言之,对象生命周期由对该对象存在的强引用的数量决定。 一旦所有强引用都被销毁,对象将被自动释放。 在您的特定场景中,内部闭包弱捕获并且已经弱引用,这不会影响目标对象的生命周期。 唯一的玩家是strongSelf ,它在不迟于外部闭包销毁之前被销毁。

暂无
暂无

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

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