强,弱引用+镜像:导致泄漏

时间:2019-01-08 20:55:23

标签: swift

下面的Parent类具有对单个子对象的强引用和弱引用。子对象永远不会释放。删除弱引用,并释放该孩子。

需要调用Mirror方法来产生此泄漏,但是我不明白为什么使用镜像会导致此行为。镜像的结果不会保留。

同时使用弱引用和强引用,仅执行父deinit!

Parent deinit

我希望看到父对象和子对象都被释放,以便日志显示:

Parent deinit
DeinitLogger deinit

删除弱引用,日志将按预期显示两个对象都已初始化。

您能帮我理解为什么会泄漏吗? (这不是游乐场,而是在应用程序中。)

class DeinitLogger {
    deinit {
        print("DeinitLogger \(#function)")
    }
}

class Parent: NSObject {

    weak var weakLogger: DeinitLogger?
    var strongLogger: DeinitLogger

    override init() {

        let logger = DeinitLogger()

        // Create a weak ref
        weakLogger = logger  // comment out this line, no leak!

        // Create a strong ref to same object.
        strongLogger = logger

        super.init()

        // Invoking mirror and adding the properties to a dict leaks when one of the
        // properties is weak.
        let dict = dictionaryOfProps()
        print(dict)
    }

    deinit {
        print("Parent \(#function)")
    }

    /// Generates a dictionary of property names -> properties
    /// e.g. "strongLogger" -> type of strongLogger.
    private func dictionaryOfProps() -> [String: Any] {
        var result = [String: Any]()
        let mirror = Mirror(reflecting: self)
        for case let(label?, value) in mirror.children {
            result[label] = value
        }
        return result
    }
}

// Chuck these two lines in a viewDidLoad(), or anywhere. 
var o: Parent? = Parent()
o = nil // everything should be freed here.

1 个答案:

答案 0 :(得分:4)

这是Swift 4.2(Xcode 10)中的一个已知错误:

ReflectionMirror.m中读取弱引用时,由于缺少发行而引起。该错误已在master分支上修复。您的程序与来自https://swift.org/download/#releases的当前“主干开发(主)”快照一起正常运行。