簡體   English   中英

將引用轉換回封閉內部的強引用,內存管理,swift

[英]convert the reference back to a strong one inside the closure, memory management, swift

我正在嘗試關閉保留周期,如下所示

 class Sample {
        deinit {
            print("Destroying Sample")
        }

        func additionOf(a: Int, b:Int) {
            print("Addition is \(a + b)")
        }

        func closure() {                
          dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in
            self?.additionOf(3, b: 3)   
            usleep(500)                 
            self?.additionOf(3, b: 5)  
          }
        }
    }

后來在某些時候,我正在做

var sample : Sample? = Sample()
sample?.closure()

dispatch_async(dispatch_get_global_queue(0, 0)) {
  usleep(100)
  sample = nil
}

輸出將是

Addition is 6
Destroying Sample

這是可以理解的,因為self在做self?.additionOf(3, b:5)之前是沒有的self?.additionOf(3, b:5)

如果我通過創建另一個引用[weak self]變量(如下所示)在閉包內部進行了更改

dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in
   guard let strongSelf = self else { return }
   strongSelf.additionOf(3, b: 3)
   usleep(500)
   strongSelf.additionOf(3, b: 5)
}

這次,輸出是

Addition is 6
Addition is 8
Destroying C

我的問題是為什么在sample = nil之后, strongSelf不會出現問題。 是因為它在sample = nil之前被捕獲在閉包內

讓我們考慮你的第二個例子:

dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in
    guard let strongSelf = self else { return }
    strongSelf.additionOf(3, b: 3)
    usleep(500)
    strongSelf.additionOf(3, b: 5)
}

這是一種常見的模式,它有效地說“如果self已被解除分配,立即return ,否則建立一個強大的參考, strongSelf ,並保持這個強大的參考,直到關閉完成。”

所以,在你的例子中,當這個調度塊開始時self不是nil ,所以一旦我們分配了strongSelf來引用它,我們現在有兩個強引用這個Sample對象,原始sample引用和這個新的strongSelf引用里面這個關閉。

因此,當你的另一個線程刪除它自己的強引用, sample ,到這個Sample對象時(通過超出范圍或通過顯式設置samplenil ),這個strongSelf強引用仍然存在,並將保持對象不被釋放(或者至少在此調度塊完成之前。

在上面的評論中,您會問:

我仍然不明白為什么strongSelf沒有改變,因為自己nil ...

強引用永遠不會被設置為nil只是因為其他一些強引用(即使它是原始的強引用)被設置為nil 參考設置為nil行為僅適用於weak引用,而不適用於強引用。

當你的代碼在第一個線程上執行sample = nil時,所做的就是刪除一個強引用。 它不會刪除對象或類似的東西。 它只是刪除了它的強大參考。 現在,調度塊有自己的強引用,所有在sample = nil時發生的事情是,具有兩個強引用的對象現在只剩下一個強引用(調度塊中的strongSelf引用)。 只有在刪除了最終的強引用時,才會釋放對象並deinit

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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