[英]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.