如何在核心数据上创建可观察对象并将其绑定到 tableView
Posted
技术标签:
【中文标题】如何在核心数据上创建可观察对象并将其绑定到 tableView【英文标题】:How do I create an observable on core data and bind it to tableView 【发布时间】:2020-04-27 14:04:04 【问题描述】:我这样获取core data
:
var persistingData: [MyDataObject] = coreData.fetchAll(fetchRequest: NSFetchRequest<MyDataObject>(entityName: "MyDataObject"))
现在我该如何着手将这些数据用于Observable
,它可以将bind
数据用于rx
tableView
?
我是否像这样创建observable
:
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()
)
但是如果我将数据传递给onNext
,我如何在observable
上使用bind()
? bind
直接在method
上使用,如下所示:
fetchAllData().bind()
我如何真正将data
放入observable
以便它可以在bind()
中使用?
编辑
我也试过这样。这是一种有效的方法吗?
func fetchAllData() -> PublishRelay<[MyDataObject]>
var persistingData: [MyDataObject] = coreData.fetchAll(fetchRequest: NSFetchRequest<MyDataObject>(entityName: "MyDataObject"))
let relay = PublishRelay<[LocalDoorCoreDataObject]>()
relay.accept(persistingDoors)
return relay
然后你可以像这样bind
它:
viewModel.fetchAllData().bind(to: tableView.rx.items(cellIdentifier: Cell.identifier, cellType: Cell.self)) row, data, cell in
cell.viewModel = data
.disposed(by: disposeBag)
这看起来合理吗,还是有其他方法?
【问题讨论】:
【参考方案1】:Rx 在处理数据流时特别有用,但您正试图将其用作单个核心数据获取请求的简单包装器。我会构建一个BehaviorRelay
来保留来自Core Data 的数据的副本,以及一个运行您的获取请求并将值报告给BehaviorRelay
的Observable,您可以在需要刷新时随时订阅。
在您的视图模型中:
let data = BehaviorRelay<[MyDataObject]>(value: [])
我会将它绑定到您的表格视图:
viewModel.data.bind(to: tableView.rx.items(cellIdentifier: Cell.identifier, cellType: Cell.self)) row, data, cell in
cell.viewModel = data
.disposed(by: disposeBag)
然后,回到你的视图模型:
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)
任何时候你需要刷新数据,你只需调用:
viewModel.loadData.subscribe().disposed(by: disposeBag)
您可以使用loadData
发出的值立即更改您的用户界面,例如显示空白屏幕或停止加载指示器。如果有,请务必在订阅前添加observeOn(MainScheduler.instance)
。
【讨论】:
【参考方案2】:让我们从您的抓取开始。
func fetchAllData() -> Observable<[MyDataObject]>
Observable.just(coreData.fetchAll(fetchRequest: NSFetchRequest<MyDataObject>(entityName: "MyDataObject")))
(上面的内容与您的 fetchAllData 所做的相同,但更简洁。)
现在想想您可能想要获取数据的所有原因...假设您有一个刷新按钮,并且您想要获取所有数据的唯一时间是用户点击该按钮时。然后在您的 viewDidLoad
(或从它调用的函数中)中,您将拥有:
let allData = refreshButton.rx.tap
.flatMap
fetchAllData()
假设我们想在表格视图上显示数据。我们想要在视图上重新加载数据的所有原因是什么?假设我们想要重新加载数据的唯一原因是allData
发出一个值。然后在viewDidLoad
(或从中调用的函数)中,您将拥有:
allData
.bind(to: tableView.rx.items(cellIdentifier: Cell.identifier, cellType: Cell.self)) row, data, cell in
cell.viewModel = data
.disposed(by: disposeBag)
就这么简单。
当然,当您设想其他时候您可能想要获取所有数据时,事情会变得更加复杂,但以上是基础知识。
【讨论】:
以上是关于如何在核心数据上创建可观察对象并将其绑定到 tableView的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SwiftUI 中使用可观察对象并与 NavigationLink 绑定?