完成块问题内的 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: {})
}
我有一个真正的具体问题。我经常收到这个,但我找不到原因。
主要问题,即使我使用 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: {}) }