将ViewModelOwners与ReactiveCocoa结合使用时如何处置DisposeBag

时间:2019-05-15 20:03:24

标签: reactive-cocoa reactive-swift viewmodelowners

ViewModelOwners介绍了如何与ReactiveCocoa CompositeDisposable一起使用

Example甚至通过ReactiveCocoa实现。

但是,我不了解disposeBag的实际处置方式,因为CompositeDisposable不会自动处置在deinit

我正在尝试该示例,并将日志消息添加到一次性对象:

func didSetViewModel(_: ViewModel, disposeBag: CompositeDisposable) {
  disposeBag += AnyDisposable {
    print("Disposed Profile")
  }
}

在释放控制器时,永远不会打印该消息。

我认为您需要手动将袋子放在deinit上,但是没有暴露相关对象,所以我无法在disposeBag中得到deinit

我想到的最好的方法是像这样使用ReactiveCocoa的lifetime

func didSetViewModel(_: ViewModel, disposeBag: CompositeDisposable) {
  disposeBag += AnyDisposable {
    print("Disposed Profile")
  }

  self.reactive.lifetime.observeEnded {
    if !disposeBag.isDisposed {
      disposeBag.dispose()
    }
  }
}

但这似乎有问题,例如如果这是ReusableViewModelOwner,那么所有个最后的disposeBags都已经被处理掉了,但是我仍然保留它们...

所以基本上,我的问题是:应该如何将ViewModelOwnersReactiveCocoa.CompositeDisposable一起使用?

1 个答案:

答案 0 :(得分:0)

如问题中所述,ReactiveSwift.CompositeDisposable不会自动处理deinit。

但是ReactiveSwift已经为此提供了一种解决方案:ScopedDisposable就是这样做的。

因此,原始问题的解决方案是使用ScopedDisposable<CompositeDisposable>而不是普通的CompositeDisposable

extension ScopedDisposable: ViewModelOwnerDisposeBagProtocol where Inner == CompositeDisposable {
    public convenience init() {
        self.init(CompositeDisposable())
    }

    private final class Wrapper: Disposable {
        var isDisposed: Bool
        let disposable: ViewModelOwnerDisposable

        init(_ disposable: ViewModelOwnerDisposable) {
            self.disposable = disposable
            isDisposed = false
        }

        func dispose() {
            disposable.dispose()
            isDisposed = true
        }
    }

    public func add(_ disposable: ViewModelOwnerDisposable) {
        inner.add(Wrapper(disposable))
    }
}

然后

func didSetViewModel(_ viewModel: ViewModel, disposeBag: ScopedDisposable<CompositeDisposable>) {
  disposeBag += AnyDisposable {
    print("Disposed Profile")
  }
}

文档已经进行了相应的更新