Swift将var函数赋值给var导致保留周期?

问题描述:

我遇到了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

在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() 
}