首页 > 解决方案 > Swift:保持对弱变量的强引用

问题描述

我有一个对其委托的引用很弱的类。在后台操作中,我需要设置委托,对类执行操作,然后释放委托。

下面的代码在调试模式下工作,但在发布模式下失败,因为在发布模式下,委托被立即释放。

protocol DocumentDelegate:class { ... }

class MyDocument {
    weak var delegate:DocumentDelegate?

    func save() {
        assert(self.delegate =! nil)
    }
}

// Later:

// (#1) Using "var" does not work:
var delegate:DocumentDelegate? = InterimDelegate()

let document = MyDocument()

document.delegate = delegate

// Compiled in Release mode, at this time the delegate is already nil!
document.save()

delegate = nil


// (#2) Using "let" does work:
let delegate:DocumentDelegate = InterimDelegate()

let document = MyDocument()

document.delegate = delegate

// Compiled in Release mode, at this time the delegate is already nil!
document.save()

我假设最后一条指令delegate = nil会导致编译器在此之前保留委托(即使用变量的“最后”时间)。然而,仔细想想,编译器优化代码并立即释放委托实例是有道理的,因为没有其他强引用。

但是,我不明白为什么编译器在使用“let”时在第二种情况下的行为方式不同。在这里,编译器也可以看到委托没有通过其他任何地方的强引用来引用,但它确实保留它直到块结束。

考虑这个问题的好方法是什么,以及保持对弱委托的强引用的好方法是什么?

标签: swiftautomatic-ref-countingweak-referencesreference-counting

解决方案


虽然我完全同意 Rob Napier 的分析,但为了完整起见,我应该注意,您也可以明确对象的生命周期:

let delegate = InterimDelegate()

withExtendedLifetime(delegate) {
    let document = MyDocument()
    document.delegate = delegate
    document.save()
}

推荐阅读