首页 > 解决方案 > 完成块内的 RxSwift 订阅问题

问题描述

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

主要问题,即使我多次使用 disposeBag 一些“订阅(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。所以我在 self 中调用 disposeBag。

场景是这样的;

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

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

Pull-To-Refresh
单击按钮 -> 推送到 VC(3 次)

更新

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

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

标签: iosswiftcallbackrx-swift

解决方案


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

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

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

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

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

推荐阅读