RxSwift Удаление одной подписки вызывает удаление другой подписки
У меня 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
деинициализируется, любое представление, являющееся источником, infoMessageAction
также деинициализируется, и это представление генерирует 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()
}
Теперь подписка удаляется по мере необходимости.