RxSwift订阅完成块内的问题

时间:2018-09-24 08:00:30

标签: ios swift callback rx-swift

我有一个具体的问题。我通常会得到这个,但找不到原因。

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

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

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工作自行处理。它只是将完成返回给viewController。所以我称自己为disposeBag。

场景如下:

  

点击按钮->推送至VC(1次)

     

上拉刷新
  点击按钮->推送至VC(两次)

     

上拉刷新
  点击按钮->推送至VC(3次)

已更新

我发现了问题。因此,我也更新了标题。原因是我正在使用self.kpiesCollectionView.collectionHeaderButton.rx.tap.subscribe( 在我的请求完成块中,但是当我移到它之外时,它运行良好。

也许这不是正确的地方,但只想学习。如何避免这种情况?即使在一个块内也该如何调用subscribe()?

1 个答案:

答案 0 :(得分:1)

我决定在此处发布答案,也许其他SO用户会发现它很有帮助。因此,如果多次调用subscribe:onNext中的代码而没有观察者发送onNext命令,则意味着您多次向观察者订阅。

现在,dispose(bag:)将在处置包被释放后处置所有订户,但是,如果该包仍然存在于您的对象上,则在UI订户的情况下(在视图控制器中,视图等),最好的做法是在week self内使用onNext:/onError/etc,以避免保留您的包/控制器的循环周期。

要“用力”处理袋子,您有三种选择:

  • 如果您使用DisposeBag,就足以重新初始化包装袋(bag = DisposeBag())。
  • 有一个CompositeDisposable像字典一样工作,这种袋子可以让您更好地控制可处置的物品,每当在袋子中添加可弃置物时{bag.insert,您就可以会得到该一次性用品的钥匙,您可以使用该钥匙呼叫remove
  • 最后一个选项(有时更像是丑陋的选项)是保留对一次性用品的引用,并直接在其上调用处置,例如:

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