didSet弱引用不按预期工作

时间:2015-10-21 22:56:30

标签: swift weak-references

我有一个小的Swift脚本,它使用弱引用:

#!/usr/bin/env swift

class Thing
{
    deinit
    {
        print("Thing object deallocated")
    }
}

class WeakThing
{
    weak var thing: Thing?
    {
        didSet
        {
            print("Set thing to \(thing)")
        }
    }
}

var thing = Thing()

let weakThing = WeakThing()
weakThing.thing = thing

thing = Thing()
print("weakThing's thing is \(weakThing.thing)")

打印:

Set thing to Optional(Test.Thing)
Thing object deallocated
weakThing's thing is nil

但是,我希望它能打印出来:

Set thing to Optional(Test.Thing)
Set thing to nil
Thing object deallocated
weakThing's thing is nil

我做错了什么?我看到该对象正在被释放,并且thing变量的值正在改变,但我的didSet代码没有执行。

2 个答案:

答案 0 :(得分:5)

当由于ARC导致弱引用自动归零时,不会调用

didSetwillSet

如果您要将属性设置为nil,则会看到didSet代码被调用。

答案 1 :(得分:0)

我知道这个问题很老,但是我偶然发现了另一个答案,实际上是在这里解决了这个问题:https://stackoverflow.com/a/19344475/4069976

对于它的价值,这是我的实现,它观察到上面引用的答案所建议的deinit。只要确保您没有使用onDeinit闭包创建任何保留周期即可!

private var key: UInt8 = 0

class WeakWatcher {
    private var onDeinit: () -> ()

    init(onDeinit: @escaping () -> ()) {
        self.onDeinit = onDeinit
    }

    static func watch(_ obj: Any, onDeinit: @escaping () -> ()) {
        watch(obj, key: &key, onDeinit: onDeinit)
    }

    static func watch(_ obj: Any, key: UnsafeRawPointer, onDeinit: @escaping () -> ()) {
        objc_setAssociatedObject(obj, key, WeakWatcher(onDeinit: onDeinit), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }

    deinit {
        self.onDeinit()
    }
}

在初始化弱变量时像这样调用它:

self.weakVar = obj
WeakWatcher.watch(obj, onDeinit: { /* do something */ })