Swift分配函数到var导致保留周期?

时间:2016-01-29 08:56:58

标签: swift2 retain-cycle

我在Swift Memory Management: Storing func in 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()

在我看来,变量tblock捕获,而blockt的属性,所以任何人都可以解释为什么没有保留周期?

1 个答案:

答案 0 :(得分: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()
}