请注意:我已经阅读了许多关于避免强参考周期的(非常多)答案和文章。但是,我正在寻找有关如何处理避免这些循环的特定副产品的指导。
在以下示例中,类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,闭包仍然需要将一个Model(即WHAT?)返回给闭包的调用者(Foo实例)。但是,由于self是nil,我不会'有一个模型可以移交。
问题
有人可以推荐在这种情况下使用的模式吗?最好,我不希望Foo检查modelGetter是否有效,或者想知道模型是否有效。出于Foo的目的,如果Foo存在,那么它必须始终能够获得它所需的模型。
或者,我是否应该重新设计Foo的需求,以考虑无法获得模型的可能性?谢谢你的帮助。
答案 0 :(得分:1)
如果Class是Foo
的所有者,建议您设置[unowned self]
而不是[weak self]
。它将解决问题。如果一个类是另一个类的所有者,它将永远不会出现问题,但如果逻辑错误,它将显示崩溃并不坏,因为它向您发出信号,表明您在项目中损坏了某些内容。
答案 1 :(得分:1)
但是,这会产生一个保留周期。
不,它没有。 foo
拥有对闭包的引用,而闭包拥有对self
的引用(显然不是foo
)。如果您在Foo
中拥有self
类型的强大属性并且将其设置为foo
,则只会获得保留周期。
假设您要这样做,我会使用以下两种模式之一:
我作为程序员假设self
将在foo
的生命周期中始终存在。在这种情况下,我会使用[unowned self]
而不是[weak self]
。如果我的假设被证明是错误的,程序将中止,我将能够根据堆栈跟踪修复错误。显然,您需要一个相当广泛的测试套件来尽可能验证该假设。
我认为self
消失是有效的,在这种情况下你有三个选择来处理消失:
() -> Model?
并使Foo
能够处理nil
模型Model
为self
,则返回默认nil
。 self
为nil
,请让闭包声明它会抛出并抛出错误。我想我可能会选择[unowned self]
,并确保我明确地在某处明确地提及它。