为什么在属性中包装ReactiveSwift MutableProperty会导致泄漏?

时间:2017-12-06 17:40:51

标签: ios swift memory-leaks reactive-cocoa reactive-swift

这里是一个Swift类,它使用ReactiveSwift,将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()进行设置,则会产生泄漏。通过&#34;造成泄漏,&#34;我的意思是它引发了泄漏工具,显示标记为Malloc 32 Bytes的泄漏对象,其中包含Leaker.init()调用Leaker.wrapperProperty.getter的堆栈跟踪。

为什么会泄漏?我发现很难确切地知道是什么导致这里分配的内存永远不会被释放。

其他一些可能有用的事实:

  • 如果我直接订阅mutableProperty
  • ,这不会泄漏
  • 如果我将mutableProperty包装在惰性属性而不是计算属性中,则不会泄漏
  • 如果我创建一个临时Leaker,例如,这不会泄漏。 let _ = Leaker()

1 个答案:

答案 0 :(得分:3)

我试过,但无法重现内存泄漏。我已使用您的确切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在其completed方法中发送deinit,因此应该可以像我在这里一样检测泄漏。

但是,为了确保我还使用没有检测到的内存泄漏仪器对此进行了分析。

既然你提到了一些不会泄漏的具体情况,那可能就是我试图重现这个问题的方式是错误的,也许你可以发布一个完整的例子?

无论如何,我没有在你发布的例子中看到错误,所以要么这是ReactiveSwift中的一个错误,要么是一个错误的正面分析器(在jjoelson指出他之前发生过ReactiveSwift)评语)