[英]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 可能超出Weak1和Weak2范圍的可能性。
但是,我注意到Weak2
存在無效的可能性,這就是我希望通過這個問題澄清的。
最終,weak 所做的只是為 self 創建一個可選變量,所以我不知道任何潛在的陷阱。 此外,在callClosure()
執行期間, Weakself1 、 strongSelf
和Weakself2都指向相同的內存地址。
讓我們一步一步來(一行一行)
// 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.