Reputation: 2291
I think it's better if I explain what I'm trying to achieve because I think the error is on my misunderstanding on how Observables work.
I have a UIViewController that contains a UITableView I'm also using RxSwift and RxDataSources, so I'm binding my tableView items like this:
vm.model
.debug()
.drive(tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
Where vm is a viewModel which contains:
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: [])
Where model is:
var model: Driver<[Model]>
This all works great the first time, the tableview displays the items, but the print from the 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
The problem is I didn't want the datasource to dispose because I wan't to update it based on the user action. If the user clicks a tableViewCell I want to update the model. Any ideas on how can I achieve this?
Sorry for such a big question.
Upvotes: 4
Views: 749
Reputation: 33967
I'm guessing that network.provider.getMarkets()
makes a network call which returns a single result and completes.
Now, getMarkets()
is the source, and tableView.rx.items
is the sink. Once the source completes, the chain is broken.
It sounds like what you want to do is create a new getMarkets
Observable every time the user taps something, as well as calling getMarkets
once for free. I would expect something like:
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: [])
Note that the only real difference is the beginning trigger.flatMap {
. Your source will then be the button or whatever the user taps on to cause the network update which won't complete until it's deleted.
(The above is untested code, but it should give you an idea of the shape you want.)
Upvotes: 2