簡體   English   中英

在聲明強自我之后在閉包中使用 [弱自我] 是否有潛在的缺點?

[英]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 可能超出Weak1Weak2范圍的可能性。

但是,我注意到Weak2存在無效的可能性,這就是我希望通過這個問題澄清的。

最終,weak 所做的只是為 self 創建一個可選變量,所以我不知道任何潛在的陷阱。 此外,在callClosure()執行期間, Weakself1strongSelfWeakself2都指向相同的內存地址。

讓我們一步一步來(一行一行)

// 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM