RxSwift Membuang satu langganan memanggil buang langganan lain
Saya memiliki PublishSubject<InfoData>
di ViewController. Dan saya berlangganan, jadi ketika itu memancarkan acara - saya tunjukkan 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)
}
Dalam ViewController saya memiliki tableView dengan header bagian. Tampilan tajuk bagian memiliki infoMessageAction: PublishSubject<InfoData?>
. Saat memulai tampilan untuk viewForHeaderInSection
saya membuat langganan antara infoMessageAction
dan 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
}
Ketika tampilan header dimulai untuk pertama kalinya, semuanya berfungsi dengan baik - infoMessageAction
memicu infoData
yang pada gilirannya memicu presentasi AlertViewController. Ketika saya menggulir tampilan tajuk di luar layar, langganan antara view.infoMessageAction
dan infoData
membuang (yang merupakan perilaku yang diharapkan sebagai tampilan itu deinited).
Tapi saya juga membuang langganan antara infoData
dan ViewController. Saya menerima event completed
dan dispose
untuk view.infoMessageAction
<-> infoData
berlangganan dan juga event completed
dan dispose
untuk infoData
<-> ViewController berlangganan.
Saya berharap bahwa hanya view.infoMessageAction
<-> infoData
langganan yang rusak. Juga kedua langganan dibuang oleh disposeBag yang berbeda. Mengapa infoData
langganan <-> ViewController dibuang dan bagaimana cara mencegahnya?
Terima kasih sebelumnya!
Jawaban
Saat Anda FutureSpendingsHeaderView
dideinisialisasi, tampilan apa pun yang merupakan sumbernya infoMessageAction
juga sedang dideinisialisasikan, dan tampilan tersebut memancarkan completed
peristiwa pada saat itu. Acara selesai itu diteruskan infoData
yang kemudian memancarkan acara selesai sendiri.
Setelah Observable mengeluarkan event yang sudah selesai, itu selesai. Itu tidak bisa memancarkan acara lagi. Jadi langganannya dibuang.
Jawaban Anda @Alex mengubah persamaan dengan mengubah urutan hal-hal di dalam tampilan Anda dideinisialisasi. DisposeBag mendapatkan deinisialisasi terlebih dahulu, yang memutus rantai yang dapat diamati sebelum tampilan mengirimkan peristiwa yang telah selesai.
Solusi yang lebih baik adalah menggunakan a PublishRelay
daripada a PublishSubject
. Relai tidak memancarkan acara yang sudah selesai.
Bahkan lebih baik dari itu adalah menyingkirkan subjek sepenuhnya dan melakukan sesuatu seperti:
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
}
Menemukan masalahnya, jika ada yang menghadapi situasi seperti itu. Di bagian tampilan tajuk, saya memulai disposeBag
sebagai konstan dan berpikir bahwa segala sesuatu yang lain ditangani oleh RxSwift itu sendiri ketika tampilan dideinited. Jadi saya memperbarui tampilan menjadi:
var disposeBag = DisposeBag()
deinit {
disposeBag = DisposeBag()
}
Sekarang langganan dibuang sesuai kebutuhan.