[英]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
模型 self
为nil
,则返回一个默认Model
。 self
为nil
抛出错误。 我想我可能会选择[unowned self]
,并确保我在某处明确引用了它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.