【问题标题】:Swift assign function to var cause retain cycle?Swift将函数分配给var导致保留周期?
【发布时间】:2016-05-06 22:43:41
【问题描述】:

我在Swift Memory Management: Storing func in var 遇到了类似的问题,但这并没有解决我的问题。

这是我的类定义:

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

    func returnInt() -> Int {
        return 1
    }

    deinit {
        print("Test deinit")
    }
}

我尝试了两种方法来为block 属性赋值,得到了完全不同的结果。第二种方法并没有引起retain circle,这很出乎意料:

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 的属性,所以谁能解释为什么没有保留周期?

【问题讨论】:

  • 有趣的是,如果您不将 t 重新分配给其他对象并让它超出范围,它的行为就像一个强引用循环,除非您包含 [unowned t] in[weak t] in。 ..

标签: swift2 retain-cycle


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2018-05-13
    • 1970-01-01
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多