首页 文章

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

提问于
浏览
4

这是一个使用ReactiveSwift的Swift类,在 Property 中包装 MutableProperty ,并在 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() 设置它,则会产生泄漏 . 通过"creates a leak,"我的意思是它引发泄漏工具,显示一个标记为 Malloc 32 Bytes 的泄漏对象,其堆栈跟踪包含 Leaker.init() ,调用 Leaker.wrapperProperty.getter .

为什么泄漏?我发现很难理解究竟是什么导致这里分配的内存永远不会被释放 .

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

  • 如果我直接订阅 mutableProperty ,这不会泄漏

  • 如果我将 mutableProperty 包装在惰性属性而不是计算属性中,则不会泄漏

  • 如果我创建一个临时的 Leaker ,这不会泄漏,例如 let _ = Leaker()

1 回答

  • 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 在其 deinit 方法中发送 completed ,因此应该可以像我在这里一样检测泄漏 .

    但只是为了确保我也用内存泄漏仪器对其进行了分析,该仪器没有检测到任何内容 .

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

    无论如何,我没有看到你发布的例子中的错误,所以要么这是ReactiveSwift中的错误,要么是探查器的错误肯定(在jjoelson在他的评论中指出之前发生过ReactiveSwift)

相关问题