完成块问题内的 RxSwift 订阅

RxSwift subscribtion inside completion block issue

我有一个真正的具体问题。我经常收到这个,但我找不到原因。

主要问题,即使我使用 disposeBag 多次调用“subscribe(onNext :”)。 但是我发现了一些东西;调用次数线性增加取决于另一个订阅。

例如;我有两个组件,在 viewController 上声明。一个是自定义 collection 视图,另一个是自定义刷新控制管理器。

self.kpiesCollectionView.collectionHeaderButton.rx.tap
    . subscribe(onNext: { [weak self] _ in
           // Push to next ViewController
       }).disposed(by: self.kpiesCollectionView.disposeBag)


refreshControl.rx.controlEvent(UIControlEvents.valueChanged).asObservable().subscribe(onNext: { () in
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
                completion()
            }
        }).disposed(by: disposeBag)

refreshControl 工作在自己处理。它只是 returns 完成到 viewController。所以我自己调用了 disposeBag。

场景是这样的;

Click Button -> Pushes to VC (1 time)

Pull-To-Refresh
Click Button -> Pushes to VC (2 time)

Pull-To-Refresh
Click Button -> Pushes to VC (3 time)

已更新

我找到问题了。这就是为什么,我也更新了标题。原因是我正在使用 self.kpiesCollectionView.collectionHeaderButton.rx.tap.subscribe( 在我的请求完成块内,但当我移到它外面时,它运行良好。

也许地方不对,只是想学习一下。我怎样才能避免这种情况。?我如何在块内调用 subscribe()?

我决定 post 在这里回答,也许其他 SO 用户会发现它有帮助。因此,如果您在 subscribe:onNext 中的代码在观察者没有发送 onNext 命令的情况下被多次调用,这意味着您多次订阅了观察者。

现在 dispose(bag:) 将在解除分配处理包时处理任何订阅者,但如果该包仍然存在于您的对象上,则订阅者将不会被解除分配,此外,在 UI 的情况下订阅者(在视图控制器、视图等中)最好在 onNext:/onError/etc 中使用 week self 以避免 bag/controller.

的保留周期

要"force"处理一个包,你有三个选择:

  • 如果你使用 DisposeBag 就足以重新初始化包 (bag = DisposeBag())。
  • 有一个像字典一样工作的CompositeDisposable,这种包可以让你更精细地控制你可以处理的东西,每当你在包里添加一个disposable(bag.insert,你会得到一把一次性钥匙,你可以用那把钥匙打电话给 remove
  • 最后一个选项,有时更像是丑陋的选项,是保留对一次性对象的引用并直接对其调用 dispose,例如:

    var myDisposable: Disposable? = nil
    
    ......
    fun iWantToSubscribe() {
        myDispsable?.dispose()
        myDisposable = myObserver.subscribe(onNext: {})
    }