I fetch core data
like this:
var persistingData: [MyDataObject] = coreData.fetchAll(fetchRequest: NSFetchRequest<MyDataObject>(entityName: "MyDataObject"))
Now how do I go about using this data for an Observable
that can bind
the data to an rx
tableView
?
Do I create an observable
like this:
func fetchAllData() -> Observable<[MyDataObject]> {
var persistingData: [MyDataObject] = coreData.fetchAll(fetchRequest: NSFetchRequest<MyDataObject>(entityName: "MyDataObject"))
return Observable.create({ observable in
observable.onNext(persistingData)
observable.onCompleted()
return Disposables.create()
})
}
But then how I use bind()
on the observable
if I pass the data to onNext
? bind
is used directly on the method
like so:
fetchAllData().bind()
How do I actually get the data
into the observable
so that it can be used in bind()
?
EDIT
I tried like this as well. Is this a valid way of doing it?
func fetchAllData() -> PublishRelay<[MyDataObject]> {
var persistingData: [MyDataObject] = coreData.fetchAll(fetchRequest: NSFetchRequest<MyDataObject>(entityName: "MyDataObject"))
let relay = PublishRelay<[LocalDoorCoreDataObject]>()
relay.accept(persistingDoors)
return relay
}
Then you can bind
to it like this:
viewModel.fetchAllData().bind(to: tableView.rx.items(cellIdentifier: Cell.identifier, cellType: Cell.self)) { row, data, cell in
cell.viewModel = data
}.disposed(by: disposeBag)
Does this seem reasonable, or is there some other way?
Rx is particularly useful when handling streams of data, but you are trying to use it as a simple wrapper around a single Core Data fetch request. I'd build a BehaviorRelay
to keep a copy of the data coming from Core Data, and an Observable that runs your fetch request and reports values to the BehaviorRelay
that you can subscribe to any time you need to refresh.
Having in your view model:
let data = BehaviorRelay<[MyDataObject]>(value: [])
I would bind it to your table view:
viewModel.data.bind(to: tableView.rx.items(cellIdentifier: Cell.identifier, cellType: Cell.self)) { row, data, cell in
cell.viewModel = data
}.disposed(by: disposeBag)
And then, back in your view model:
var loadData: Observable<[MyDataObject]> {
return Observable.deferred { [unowned self] in
return Observable.just(self.coreData.fetchAll(fetchRequest: NSFetchRequest<MyDataObject>(entityName: "MyDataObject")))
}.do(onNext: { [unowned self] data in
self.data.accept(data)
}
}
Anytime you need to refresh data, you just call:
viewModel.loadData.subscribe().disposed(by: disposeBag)
You can use the value emitted by loadData
to make immediate changes to your UI, such as displaying an empty screen or stopping the loading indicator. If you do, make sure to add observeOn(MainScheduler.instance)
before subscribing.