完成块内的 RxSwift 订阅问题

Posted

技术标签:

【中文标题】完成块内的 RxSwift 订阅问题【英文标题】:RxSwift subscribtion inside completion block issue 【发布时间】:2018-09-24 08:00:29 【问题描述】:

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

主要问题,即使我多次使用 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 工作在 self 中处理。它只是将完成返回给 viewController。所以我在 self 中调用 disposeBag。

场景是这样的;

单击按钮 -> 推送到 VC(1 次)

下拉刷新 单击按钮 -> 推送到 VC(2 次)

下拉刷新 单击按钮 -> 推送到 VC(3 次)

更新

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

也许它不是正确的地方,但只是想学习。我怎样才能避免这种情况。?即使在块内,我如何调用 subscribe()?

【问题讨论】:

从你的描述看来,你多次调用 subscribe 而没有处理掉之前的一次性。如果您发布subscribe 发生的代码,这将有所帮助。我有一种感觉,它被多次调用。尝试只订阅一次,或者在再次订阅之前调用 dispose。 @danypata 但为什么订阅结束时的 .disposed(by: self.kpiesCollectionView.disposeBag) 不起作用。我认为它必须处理这个问题。我应该如何处理它? 最后dispose,直到bag被释放后才会dispose订阅者。这是一种更方便的处理方式。 【参考方案1】:

我决定在这里发布一个答案,也许其他 SO 用户会觉得它有帮助。因此,如果您在subscribe:onNext 中的代码被多次调用,而观察者没有发送onNext 命令,这意味着您多次订阅了观察者。

现在dispose(bag:) 将在 dispose 包被释放时释放任何订阅者,但如果包仍然存在于您的对象上,则订阅者将不会被释放,此外,对于 UI 订阅者(在视图控制器、视图、等)最好在onNext:/onError/etc 内使用week self 以避免保留包/控制器的循环。

要“强制”处理袋子,您有三个选择:

如果您使用 DisposeBag,重新初始化包 (bag = DisposeBag()) 就足够了。 有一个CompositeDisposable 像字典一样工作,这种袋子可以让你更精确地控制你可以丢弃的东西,每当你在袋子里添加一个disposeble(bag.insert,你会得到一个钥匙对于该一次性用品,您可以使用该密钥致电remove

最后一个选项,有时更像是丑陋的选项,是保留对一次性的引用并直接在其上调用 dispose,例如:

var myDisposable: Disposable? = nil

......
fun iWantToSubscribe() 
    myDispsable?.dispose()
    myDisposable = myObserver.subscribe(onNext: )

【讨论】:

以上是关于完成块内的 RxSwift 订阅问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 RxSwift 订阅数组更改?

等待多个可观察请求完成使用 RXSwift

如何在 RxSwift 中取消订阅 Observable?

RxSwift 订阅序列

RxSwift 错误处理订阅

RxSwift 共享订阅执行顺序