【发布时间】:2019-01-09 06:28:35
【问题描述】:
下面的Parent 类对单个子对象具有强引用和弱引用。子对象永远不会被释放。删除弱引用并释放孩子。
调用Mirror 方法是造成这种泄漏的必要条件,但我不明白为什么使用镜像会导致这种行为。不保留镜像的结果。
对于弱引用和强引用,只有父 deinit 被执行!
Parent deinit
我希望看到父对象和子对象都被释放,因此日志显示:
Parent deinit
DeinitLogger deinit
删除弱引用,日志显示两个对象 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.
【问题讨论】:
-
我在一个应用程序中发现了这个问题,并将其归结为一个操场。但是,当然,将此代码翻译回 App 并且它确实可以正常工作。啊!回到沸腾状态。谢谢。
-
好吧...我回到应用程序并更改了我的煮沸食谱。现在有一个
Mirror参与其中。弱 ref + mirror 甚至在应用程序中也会导致泄漏! -
我可以重现这个问题,但我承认我不知道这里发生了什么。 – 代替
let dict = dictionaryOfProps(); print(dict)在 Parent.init 方法中执行for _ in Mirror(reflecting: self).children { }就足够了。 -
是的,必须包含
children的一些迭代。谢谢你检查我的眼睛。这并不明显,是吗。我想我会针对 Swift 打开一个错误。 -
即bugs.swift.org/browse/SR-8878,已经在开发分支中修复了。
标签: swift