Here's a Swift class that uses ReactiveSwift, wrapping a MutableProperty
in a Property
, and adding a subscription to that Property
in a 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)
}
}
If I give another class a property of type Leaker?
, and then set it using self.leaker = Leaker()
, this creates a leak. By "creates a leak," I mean it sets off the Leaks instrument, showing a leaked object labeled Malloc 32 Bytes
, with a stack trace that includes Leaker.init()
calling Leaker.wrapperProperty.getter
.
Why does this leak? I'm finding it hard to understand exactly what is causing the memory allocated here to never be released.
Some other facts that might be useful:
mutableProperty
directly mutableProperty
in a lazy property instead of a computed property Leaker
, eg let _ = Leaker()
I tried, but was not able to reproduce the memory leak. I've used your exact Leaker
class with this code:
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")
}
One thing to note is that MutableProperty
sends completed
in its deinit
method, so it should be possible to detect a leak the way I did here.
But just to be sure I also profiled this with the memory leaks instrument which detected nothing.
Since you mentioned some specific circumstances in which this does not leak for you it might just be that the way I'm trying to reproduce the issue is wrong, maybe you can post a complete example?
Anyway, I don't see an error in the example you posted, so either this is a bug in ReactiveSwift, or its a false positive by the profiler (which has happened with ReactiveSwift before as jjoelson pointed out in his comment)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.