RxSwift 1つのサブスクリプションを破棄すると、別のサブスクリプションの破棄が呼び出されます
私が持っているPublishSubject<InfoData>
のViewControllerに。そして私はそれを購読しているので、それがイベントを発行するとき-私は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には、セクションヘッダー付きのtableViewがあります。セクションヘッダービューにはinfoMessageAction: PublishSubject<InfoData?>
。があります。のビューを開始するときにviewForHeaderInSection
、infoMessageAction
との間でサブスクリプションを作成しますinfoData
。
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = FutureSpendingsHeaderView(frame: frame)
view.infoMessageAction
.compactMap { $0 }
.bind(to: infoData)
.disposed(by: view.disposeBag)
return view
}
ヘッダービューが初めて開始されると、すべて正常に機能します-infoMessageAction
トリガーされ、infoData
AlertViewControllerの表示がトリガーされます。ヘッダービューを画面を超えてスクロールするview.infoMessageAction
と、サブスクリプションとinfoData
ディスポーズが行われます(これは、ビューが定義されたときに予想される動作です)。
しかし、infoData
とViewControllerの間のサブスクリプションも破棄されます。私は、受信event completed
とdispose
のためのview.infoMessageAction
< - >infoData
サブスクリプションともevent completed
やdispose
のためのinfoData
< - >のViewControllerのサブスクリプション。
view.infoMessageAction
<->infoData
サブスクリプションだけが壊れることを期待しています。また、両方のサブスクリプションが異なるdisposeBagによって破棄されました。infoData
<-> ViewControllerサブスクリプションが破棄されるのはなぜですか?それを防ぐ方法は?
前もって感謝します!
回答
あなたは、ときFutureSpendingsHeaderView
の源であるものは何でもビュー、deinitializedさinfoMessageAction
もdeinitialized、およびそのビューが放出されcompleted
、その時点でイベントを。その完了したイベントは渡され、infoData
その後、独自の完了したイベントが発行されます。
Observableが完了したイベントを発行すると、それが実行されます。これ以上イベントを発行することはできません。したがって、サブスクリプションは破棄されます。
あなたの答え@Alexは、ビュー内のものが非初期化される順序を変更することによって方程式を変更します。disposeBagは最初に非初期化され、ビューが完了したイベントを送信する前に監視可能なチェーンを切断します。
より良い解決策は、PublishRelay
ではなくを使用することですPublishSubject
。リレーは完了したイベントを発行しません。
それよりもさらに良いのは、主題を完全に取り除き、次のようなことをすることです。
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = FutureSpendingsHeaderView(frame: frame)
view.infoMessageAction
.compactMap { $0 }
.subscribe(onNext: { [weak self] (title, message) in
self?.presentInfoSheetController(with: title, message: message)
})
.disposed(by: view.disposeBag)
return view
}
誰かがそのような状況に直面した場合、問題を見つけました。セクションヘッダービューではdisposeBag
、定数として開始し、ビューが終了すると、他のすべてはRxSwift自体によって処理されると考えました。そこで、ビューを次のように更新しました。
var disposeBag = DisposeBag()
deinit {
disposeBag = DisposeBag()
}
これで、サブスクリプションは必要に応じて破棄されます。