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:
- This doesn't leak if I subscribe to
mutablePropertydirectly - This doesn't leak if I wrap
mutablePropertyin a lazy property instead of a computed property - This doesn't leak if I create a temporary
Leaker, e.g.let _ = Leaker()