2016-01-29 94 views
3

我遇到了Swift Memory Management: Storing func in var中的類似問題,但這並未解決我的問題。Swift將var函數賦值給var導致保留週期?

這裏是我的類定義:

class Test { 
    var block: (() -> Int)? 

    func returnInt() -> Int { 
     return 1 
    } 

    deinit { 
     print("Test deinit") 
    } 
} 

我嘗試了兩種方式來分配價值block財產,得到了完全不同的結果。第二種方法沒有造成保留圈,這是相當出人意料:

var t = Test() 
// This will lead to retain cycle 
// t.block = t.returnInt 
// I thought this will also lead to retain cycle but actually didn't 
t.block = { 
    return t.returnInt() 
} 
t = Test() 

在我看來,變量tblockblockt屬性捕獲,所以任何人都可以解釋爲什麼沒有一個保留週期?

+1

有趣的是,如果你不重新分配't'到別的東西,只是讓它掉下來的範圍,但它像一個強參考週期,除非您在''中包含'[無主t]'或''中的[弱t] – Rob

回答

2

在Swift中,所有捕獲的變量都通過引用捕獲(Apple Blocks術語中,所有捕獲的本地變量都是__block)。因此塊內的t與塊外的t共享;該塊不保存t的獨立副本。

本來,有在所述第二情況下的保留週期太,作爲塊保持參考的t此共享副本,並t指向第一Test對象,並且該Test對象的block屬性指向該塊。但是,當您重新分配共享變量t(在塊的內部和外部都可見)時,會中斷保留週期,因爲t不再指向第一個Test對象。


在第一種情況中,t被有效地捕獲值,這是因爲t在表達t.returnInt立即評估,而不是被捕捉爲在一個塊中的變量。因此,在塊之後重新分配t對塊沒有影響,並且不會中斷保留週期。所以,你能想到的

t.block = t.returnInt 

爲一種像

let tmp = t 
t.block = { 
    return tmp.returnInt() 
}