完成块内的 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 订阅问题的主要内容,如果未能解决你的问题,请参考以下文章