Наблюдаемый быть расположенным раньше времени
Я думаю, что будет лучше, если я объясню, чего я пытаюсь достичь, потому что я думаю, что ошибка заключается в моем непонимании того, как работают Observables.
У меня есть UIViewController, который содержит UITableView, я также использую RxSwift и RxDataSources, поэтому я связываю свои элементы tableView следующим образом:
vm.model
.debug()
.drive(tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
Где vm - модель представления, которая содержит:
self.model = self.network.provider.getMarkets()
.map { (markets: [Market]) -> [Row] in
var rows = [Row]()
for market in markets {
rows.append(.market(market: market))
}
return rows
}
.map { (rows: [Row]) -> [Model] in
return [Model(section: .market, items: rows)]
}
.shareReplay(1)
.asDriver(onErrorJustReturn: [])
Где модель:
var model: Driver<[Model]>
Все это прекрасно работает в первый раз, в табличном представлении отображаются элементы, но печать из debug ():
2017-04-28 20:07:21.382: MarketAndLanguageSelectionViewController.swift:36 (viewDidLoad()) -> subscribed
2017-04-28 20:07:22.287: MarketAndLanguageSelectionViewController.swift:36 (viewDidLoad()) -> Event next(*Multiple items*)
2017-04-28 20:07:22.289: MarketAndLanguageSelectionViewController.swift:36 (viewDidLoad()) -> Event completed
2017-04-28 20:07:22.289: MarketAndLanguageSelectionViewController.swift:36 (viewDidLoad()) -> isDisposed
Проблема в том, что я не хотел, чтобы источник данных располагался, потому что я не хочу обновлять его в зависимости от действий пользователя. Если пользователь нажимает tableViewCell, я хочу обновить модель. Есть идеи, как мне этого добиться?
Извините за такой большой вопрос.
1 ответ
Я предполагаю, что network.provider.getMarkets()
делает сетевой вызов, который возвращает один результат и завершает.
Сейчас, getMarkets()
является источником, и tableView.rx.items
это раковина. Как только источник завершается, цепочка разрывается.
Похоже, что вы хотите сделать, это создать новый getMarkets
Наблюдается каждый раз, когда пользователь что-то нажимает, а также звонит getMarkets
один раз бесплатно Я ожидал бы что-то вроде:
let markets = trigger.flatMap {
self.network.provider.getMarkets()
}.map { (markets: [Market]) -> [Row] in
var rows = [Row]()
for market in markets {
rows.append(.market(market: market))
}
return rows
}.map { (rows: [Row]) -> [Model] in
return [Model(section: .market, items: rows)]
}.startWith(self.network.provider.getMarkets())
.shareReplay(1)
.asDriver(onErrorJustReturn: [])
Обратите внимание, что единственная реальная разница - это начало trigger.flatMap {
, Тогда вашим источником будет кнопка или все, что пользователь нажимает, чтобы вызвать обновление сети, которое не будет завершено, пока оно не будет удалено.
(Выше приведен непроверенный код, но он должен дать вам представление о форме, которую вы хотите.)