将 ViewModelOwners 与 ReactiveCocoa 一起使用时如何处理 DisposeBag

How to dispose DisposeBag when using ViewModelOwners with ReactiveCocoa

ViewModelOwners 记录如何使用 ReactiveCocoa CompositeDisposable

Example 甚至是用 ReactiveCocoa 实现的。

但是,我不明白 disposeBag 是如何实际处理的,因为 CompositeDisposable 不会在 deinit

上自动处理

我正在尝试这个例子并向一次性文件添加一条日志消息:

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

当控制器被解除分配时从不打印该消息。

我认为你需要在 deinit 上手动处理包,但是关联的对象没有暴露,所以我无法在 deinit 中获取 disposeBag

我想出的最好的方法是像这样使用 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 一起使用?

如问题中所述,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")
  }
}

文档已经相应更新