【问题标题】:Why does wrapping a ReactiveSwift MutableProperty in a Property cause a leak?为什么将 ReactiveSwift MutableProperty 包装在 Property 中会导致泄漏?
【发布时间】:2018-05-20 16:36:28
【问题描述】:

这是一个使用 ReactiveSwift 的 Swift 类,将 MutableProperty 包装在 Property 中,并在 ScopedDisposable 中添加对该 Property 的订阅:

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() 设置它,这会造成泄漏。通过“创建泄漏”,我的意思是它触发了泄漏工具,显示了一个标记为 Malloc 32 Bytes 的泄漏对象,以及一个包含 Leaker.init() 调用 Leaker.wrapperProperty.getter 的堆栈跟踪。

为什么会泄漏?我发现很难准确理解是什么导致此处分配的内存永远不会被释放。

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

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

【问题讨论】:

  • 谢谢!我们使用的是 ReactiveSwift 2.0。将尝试新版本。
  • 看起来是fixed in 2.0,所以也许这不是问题。
  • 我也可以看到泄漏。但我不必释放 Leaker 对象。如果我保留对Leaker 对象的引用,它甚至会显示出来。堆栈跟踪显示 Property.init(unsafeProducer: SignalProducer&lt;Value, NoError&gt;) 作为源。

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


【解决方案1】:

我试过了,但无法重现内存泄漏。我已经使用您的确切 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 之前已经发生过这种情况)

【讨论】:

    猜你喜欢
    • 2013-07-12
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多