Swift:保持对弱变量的强引用

Mar*_*ark 2 weak-references reference-counting automatic-ref-counting 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()
Run Code Online (Sandbox Code Playgroud)

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

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

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

Rob*_*Rob 5

虽然我完全同意 Rob Napier\xe2\x80\x99s 的分析,但为了完整起见,我应该指出,您还可以明确对象的生命周期:

\n
let delegate = InterimDelegate()\n\nwithExtendedLifetime(delegate) {\n    let document = MyDocument()\n    document.delegate = delegate\n    document.save()\n}\n
Run Code Online (Sandbox Code Playgroud)\n