这是一个使用 ReactiveSwift 的 Swift 类,将 MutableProperty
包装在 Property
中,并在 中添加对该
:Property
的订阅>ScopedDisposable
class Leaker {
let mutableProperty = MutableProperty<Int>(0)
var wrapperProperty: Property<Int> {
return Property(self.mutableProperty)
}
private var disposable: ScopedDisposable<AnyDisposable>?
init() {
let disposable = CompositeDisposable()
disposable += self.wrapperProperty.producer
.startWithValues { value in
print("\(value)")
}
self.disposable = ScopedDisposable(disposable)
}
}
如果我给另一个类一个 Leaker?
类型的属性,然后使用 self.leaker = Leaker()
设置它,这会造成泄漏。我所说的“造成泄漏”是指它触发了 Leaks 工具,显示了一个标记为 Malloc 32 Bytes
的泄漏对象,以及包含 Leaker.init()
的堆栈跟踪调用 Leaker.wrapperProperty.getter
。
为什么会泄漏?我发现很难准确理解是什么导致此处分配的内存永远不会被释放。
其他一些可能有用的事实:
- 如果我直接订阅
mutableProperty
,这不会泄漏 - 如果我将
mutableProperty
包装在惰性属性而不是计算属性中,这不会泄漏 - 如果我创建一个临时的
Leaker
,这不会泄漏,例如让 _ = Leaker()
最佳答案
我试过了,但无法重现内存泄漏。我在这段代码中使用了你的 Leaker
类:
final class OtherClass {
let leaker: Leaker?
init() {
self.leaker = Leaker()
}
}
var otherClass: OtherClass? = OtherClass()
var mutablePropertyCompleted = false
otherClass!.leaker!.mutableProperty.producer.startWithCompleted {
mutablePropertyCompleted = true
}
var wrappedPropertyCompleted = false
otherClass!.leaker!.wrapperProperty.producer.startWithCompleted {
wrappedPropertyCompleted = true
}
otherClass = nil
if(!mutablePropertyCompleted) {
print("LEAK")
}
if(!wrappedPropertyCompleted) {
print("LEAK")
}
需要注意的一件事是 MutableProperty
在它的 deinit
方法中发送了 completed
,所以应该可以像我这样检测泄漏在这里做了。
但为了确定,我还使用未检测到任何内容的内存泄漏工具对此进行了概要分析。
既然你提到了一些特定的情况,在这些情况下这不会对你造成泄漏,这可能只是我尝试重现问题的方式是错误的,也许你可以发布一个完整的例子?
无论如何,我在您发布的示例中没有看到错误,所以这要么是 ReactiveSwift 中的错误,要么是探查器的误报(正如 jjoelson 在他的评论中指出的那样,ReactiveSwift 之前已经发生过这种情况)
关于ios - 为什么在属性中包装 ReactiveSwift MutableProperty 会导致泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47680349/