繁体   English   中英

Swift-在基于闭包的配置中避免强大的参考周期

[英]Swift - Avoiding strong reference cycles in closure-based configuration

请注意:我已经阅读了很多(非常多)的答案和文章,这些主题都是关于避免强参考周期的。 但是,我正在寻找有关如何处理避免这些周期的特定副产品的指南。

在以下示例中,将类Foo设计为使用闭包进行配置。 缓存对闭包的引用以供以后使用。

每当需要Model数据时,都会调用该闭包。 为了使Foo正常工作,数据必须存在。

class Foo
{
    typealias ModelGetter = (() -> Model)
    fileprivate var _modelGetter: ModelGetter!

    ...

    func configure(with modelGetter: @escaping ModalGetter)
    {
        _modelGetter = modelGetter
    }

    func printLastestModel()
    {
        // Get the latest model, do something with it.
        precondition(_modelGetter != nil)
        let model = _modelGetter()
        print(model)
    }
}

在上面的代码中,_modelGetter被隐式展开。 尽管我可以将其定义为Optional ,并根据需要对其进行解包,但是Foo始终需要设置闭包才能正常工作,因此需要进行隐式解包。

制作Foo实例并进行配置:

let foo = Foo()
foo.configure(with: { self.makeModel() })
foo.printLatestModel()

但是,这创建了一个保留周期。

因此,使用[weak self] ,我们检查self的可选性:

foo.configure(with: { [weak self] in
    guard let strongSelf = self else { return **WHAT** }
    return strongSelf.makeModel()
})

问题

这要求即使self可能为nil,闭包仍然需要向闭包的调用者(Foo实例)返回一个Model(即WHAT?)。但是,由于self为nil,因此我没有Model交出。

有人可以推荐在这种情况下使用的模式吗? 最好,我不希望Foo检查modelGetter是否有效,或者不知道Model是否有效。 出于Foo的目的,如果Foo存在,那么它必须始终能够获得所需的模型。

或者,我是否应该重新设计Foo的需求,以考虑到无法购买模型的可能性? 感谢您的任何帮助。

如果Class是Foo的所有者,建议设置[unowned self]而不是[weak self] 它将解决问题。 如果一个类是另一个类的所有者,它将永远不会出现问题,但如果逻辑错误,它将出现崩溃。 这还不错,因为它向您发出信号,表明您在项目中破坏了某些内容。

但是,这创建了一个保留周期。

不,不是。 foo拥有对闭包的引用,而闭包拥有对self的引用(显然不是foo )。 如果您self具有Foo类型的强属性并将其设置为foo ,则只会得到一个保留周期。

假设您将要这样做,我将使用以下两种模式之一:

  • 我以程序员的身份假设,在foo整个生命周期中, self永远都会存在。 在那种情况下,我将使用[unowned self]而不是[weak self] 如果我的假设被证明是错误的,程序将中止,并且我将能够基于堆栈跟踪来修复该错误。 显然,您将需要一个相当广泛的测试套件来尽可能地验证假设。

  • 我认为self消失是有效的,在这种情况下,您对如何处理消失有三种选择:

    • 使闭包的返回类型为可选,即() -> Model? 并使Foo能够处理nil模型
    • 如果selfnil ,则返回一个默认Model
    • 使闭包声明它抛出并在selfnil抛出错误。

我想我可能会选择[unowned self] ,并确保我在某处明确引用了它。

暂无
暂无

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

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