RxSwift 处理一个订阅调用处理另一个订阅
RxSwift Disposing one subscription invokes dispose of another subscription
我在 ViewController 中有一个 PublishSubject<InfoData>
。我订阅了它,所以当它发出一个事件时 - 我显示 UIAlertViewController.
let infoData = PublishSubject<InfoData>()
private func bindInfoData() {
infoData.subscribe(onNext: { [weak self] (title, message) in
self?.presentInfoSheetController(with: title, message: message)
}).disposed(by: disposeBag)
}
在 ViewController 中,我有一个包含 header 部分的 tableView。 header 部分视图有一个 infoMessageAction: PublishSubject<InfoData?>
。启动 viewForHeaderInSection
的视图时,我在 infoMessageAction
和 infoData
之间进行订阅。
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = FutureSpendingsHeaderView(frame: frame)
view.infoMessageAction
.compactMap { [=11=] }
.bind(to: infoData)
.disposed(by: view.disposeBag)
return view
}
当 header 视图首次启动时一切正常 - infoMessageAction
触发 infoData
进而触发 AlertViewController 的显示。
当我将 header 视图滚动到屏幕之外时,view.infoMessageAction
和 infoData
之间的订阅将被处理(这是视图被取消时的预期行为)。
但我也处理了 infoData
和 ViewController 之间的订阅。我收到 event completed
和 dispose
的 view.infoMessageAction
<-> infoData
订阅以及 event completed
和 dispose
的 infoData
<-> ViewController 订阅。
我预计只有 view.infoMessageAction
<-> infoData
订阅会中断。两个订阅也由不同的 disposeBag 处理。为什么 infoData
<-> ViewController 订阅会被处置以及如何防止它?
提前致谢!
找到问题了,如果有人遇到这样的情况。
在 header 视图部分,我将 disposeBag
初始化为常量,并认为当视图被取消时,其他一切都由 RxSwift 本身处理。
所以我将视图更新为:
var disposeBag = DisposeBag()
deinit {
disposeBag = DisposeBag()
}
现在订阅会根据需要处理。
当您的 FutureSpendingsHeaderView
被取消初始化时,作为 infoMessageAction
来源的任何视图也将被取消初始化,并且该视图会在那时发出一个 completed
事件。已完成的事件将传递给 infoData
,后者会发出自己的已完成事件。
一旦一个 Observable 发射了一个完成的事件,它就完成了。它不能再发出任何事件。所以对它的订阅被处理掉了。
你的回答@Alex 通过改变视图中的事物被取消初始化的顺序来改变等式。 disposeBag 现在首先取消初始化,这会在视图发送完成的事件之前中断可观察链。
更好的解决方案是使用 PublishRelay
而不是 PublishSubject
。中继不会发出已完成的事件。
甚至比这更好的方法是完全摆脱这个主题并做类似的事情:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = FutureSpendingsHeaderView(frame: frame)
view.infoMessageAction
.compactMap { [=10=] }
.subscribe(onNext: { [weak self] (title, message) in
self?.presentInfoSheetController(with: title, message: message)
})
.disposed(by: view.disposeBag)
return view
}
我在 ViewController 中有一个 PublishSubject<InfoData>
。我订阅了它,所以当它发出一个事件时 - 我显示 UIAlertViewController.
let infoData = PublishSubject<InfoData>()
private func bindInfoData() {
infoData.subscribe(onNext: { [weak self] (title, message) in
self?.presentInfoSheetController(with: title, message: message)
}).disposed(by: disposeBag)
}
在 ViewController 中,我有一个包含 header 部分的 tableView。 header 部分视图有一个 infoMessageAction: PublishSubject<InfoData?>
。启动 viewForHeaderInSection
的视图时,我在 infoMessageAction
和 infoData
之间进行订阅。
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = FutureSpendingsHeaderView(frame: frame)
view.infoMessageAction
.compactMap { [=11=] }
.bind(to: infoData)
.disposed(by: view.disposeBag)
return view
}
当 header 视图首次启动时一切正常 - infoMessageAction
触发 infoData
进而触发 AlertViewController 的显示。
当我将 header 视图滚动到屏幕之外时,view.infoMessageAction
和 infoData
之间的订阅将被处理(这是视图被取消时的预期行为)。
但我也处理了 infoData
和 ViewController 之间的订阅。我收到 event completed
和 dispose
的 view.infoMessageAction
<-> infoData
订阅以及 event completed
和 dispose
的 infoData
<-> ViewController 订阅。
我预计只有 view.infoMessageAction
<-> infoData
订阅会中断。两个订阅也由不同的 disposeBag 处理。为什么 infoData
<-> ViewController 订阅会被处置以及如何防止它?
提前致谢!
找到问题了,如果有人遇到这样的情况。
在 header 视图部分,我将 disposeBag
初始化为常量,并认为当视图被取消时,其他一切都由 RxSwift 本身处理。
所以我将视图更新为:
var disposeBag = DisposeBag()
deinit {
disposeBag = DisposeBag()
}
现在订阅会根据需要处理。
当您的 FutureSpendingsHeaderView
被取消初始化时,作为 infoMessageAction
来源的任何视图也将被取消初始化,并且该视图会在那时发出一个 completed
事件。已完成的事件将传递给 infoData
,后者会发出自己的已完成事件。
一旦一个 Observable 发射了一个完成的事件,它就完成了。它不能再发出任何事件。所以对它的订阅被处理掉了。
你的回答@Alex 通过改变视图中的事物被取消初始化的顺序来改变等式。 disposeBag 现在首先取消初始化,这会在视图发送完成的事件之前中断可观察链。
更好的解决方案是使用 PublishRelay
而不是 PublishSubject
。中继不会发出已完成的事件。
甚至比这更好的方法是完全摆脱这个主题并做类似的事情:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = FutureSpendingsHeaderView(frame: frame)
view.infoMessageAction
.compactMap { [=10=] }
.subscribe(onNext: { [weak self] (title, message) in
self?.presentInfoSheetController(with: title, message: message)
})
.disposed(by: view.disposeBag)
return view
}