Я начинаю свое приключение с RxSwift, уже имея небольшой опыт работы с React в js. Я думаю, что моя проблема распространена, но я не уверен, как описать ее в краткой абстрактной форме, поэтому вместо этого я опишу ее на примере.
Я создаю iOS приложение, показывающее некоторые диаграммы , Интересующая часть состоит из ChartAreaController, ChartInfoController, оба встроены в ChartController. Первый контроллер - это область, показывающая некоторый график (основанный на свойстве rx chartData), а второй, среди прочих, будет иметь ползунок, чтобы пользователь мог ограничить показанное значение x (свойство rx selectedXRange), которое должно быть между некоторыми минимальными и максимальными значениями. Минимальное / максимальное значение определяется текущими данными графика.
Поведение, когда диаграмма изменения ползунка определена в ChartController:
override func viewDidLoad() {
super.viewDidLoad()
(...)
chartInfoController.selectedXRange.asObservable()
.subscribe(onNext: { [unowned self] selectedXRange in
(...)
let chartData = self.filterChartData(from: self.rawChartData, in: selectedXRange)
self.chartAreaController.chartData.accept(chartData)
}).disposed(by: disposeBag)
Метод filterChartData () просто отфильтровывает данные, которых нет в диапазоне, но ради аргумента мы могу предположить, что это очень дорого, и я не хочу, чтобы он запускался дважды, когда в этом нет необходимости.
Когда пользователь изменяет график, который он или она хочет показать, новые данные поступают с сервера (снова ChartController) :
private func handleNewData(_ rawChartData: ChartData) {
self.rawChartData = rawChartData
guard let allowedXRange = rawChartData.xRange() else { return }
let selectedXRange = chartInfoController.selectedXRange.value
let newSelectedXRange = calculateSelectedXRange(currentSelectedDays: selectedDaysRange, availableDaysRange: daysRange)
let chartData = filterChartData(from: rawChartData, in: selectedXRange)
self.chartInfoController.allowedXRange = allowedXRange //this line is not crucial
self.chartInfoController.selectedXRange.accept(newSelectedXRange)
self.chartAreaController.chartData.accept(rawChartData)
}
Таким образом, при поступлении новых данных диаграммы может случиться так, что текущий выбранный xRange должен быть обрезан из-за новых значений min / max данных. Таким образом, побочным эффектом метода будет изменение selectedXRange и, в свою очередь, запуск подписки, которую я вставил ранее. Поэтому, когда приходят новые данные, chartData обновляется дважды, и я не хочу, чтобы это произошло.
Конечно, я могу закомментировать последнюю строку метода handleNewData (), но мне это не очень нравится , поскольку основной причиной существования handleNewData () является установка chartData, а с закомментированной строкой его цель будет достигнута из-за побочного эффекта метода (который обновляет ползунок). Неприемлемо.
В chartData я все равно добавил газ, потому что быстро движущийся ползунок приведет ко многим обновлениям, и это частично решит мою проблему (chartData обновляется только один раз). Но, как вы, возможно, помните, метод filterChartData () является дорогостоящим, и эта часть будет по-прежнему выполняться дважды.
Таким образом, вопрос в том, в порядке ли мой общий план решения проблемы, или он должен быть обработан иначе? На этом этапе я пришел к выводу, что я ищу способ временного отключения определенной подписки на selectedXRange (без повреждения других подписок на эту переменную). Временное значение:
(...)
//disable subscription
self.chartInfoController.selectedXRange.accept(newSelectedXRange)
self.chartAreaController.chartData.accept(rawChartData)
//enable subscription
(...)
Мне кажется, это git, поскольку ChartController как владелец подписки и средство изменения значений может захотеть отключить подписку, когда ему это удобно (не так ли?).
Поддерживает ли RxSwift что-то подобное? Если нет, то я думаю, что смогу достичь этого сам, например, через свойство bool в ChartController или добавив подписку в отдельный disposeBag, который я бы удалил, а затем пересоздал бы подписку. Но хорошо ли это делать? Например, решение bool может быть подвержено плохому обращению при возникновении какой-либо ошибки, а утилизация / воссоздание может быть как-то дорогостоящим, и это может быть случай, когда утилизация не предназначалась для такого использования.
Есть ли лучшая практика для обработки таких ситуаций? Как я уже сказал, я думаю, что проблема является общей, поэтому я надеюсь, что есть каноническое решение :) Спасибо за любой ответ, извините за длинный пост.