rx-swift - 有没有办法简化数据转换?
问题描述
有一个函数从服务器调用 API 返回Observable<DataFromServer>
。
我想将它转换为 UI 中的必要数据并制作它Observable<[DataForUI>
。
我做了一个如下示例,但我想简化转换部分。
你能告诉我是否有办法吗?
// Models
struct DataFromServer {
var name: String
var score: Int
}
struct DataForUI {
var displayName: String
var displayScore: String
}
// API function
func fetch() -> Observable<[DataFromServer]> {
// ...
}
// output
var resultData: PublishRelay<[DataForUI]> = PublishRelay()
// Sample Code
ActionSubject // Trigger for fetch()
.flatMapLatest { fetch() }
// I want to simplify the code below.
.flatMap { data -> Observable<[DataForUI]> in
return Observable.just(data.map {
DataForUI(displayName: “convert \($0.name)”, displayScore: “convert \($0.score)”)
})
}
.bind(to: resultData)
.disposed(by: disposeBag)
解决方案
你有很多不同的选择...
首先,我会做一个扩展来处理实际的转换:
extension DataForUI {
init(serverData: DataFromServer) {
displayName = "convert \(serverData.name)"
displayScore = "convert \(serverData.score)"
}
}
然后你可以只映射/映射:
func sampleCode(actionSubject: Observable<Void>, disposeBag: DisposeBag) {
actionSubject
.flatMapLatest { fetch() }
.map { $0.map { DataForUI(serverData: $0) } }
.bind(to: resultData)
.disposed(by: disposeBag)
}
这是相同的想法,但传入 init 方法而不是闭包:
func sample1Code(actionSubject: Observable<Void>, disposeBag: DisposeBag) {
actionSubject
.flatMapLatest { fetch() }
.map { $0.map(DataForUI.init(serverData:)) }
.bind(to: resultData)
.disposed(by: disposeBag)
}
你可以在 Observable 上写一个扩展来处理 map/map 操作:
extension ObservableType where Element: Sequence {
func mapArray<Result>(_ transform: @escaping (Self.Element.Element) throws -> Result) -> RxSwift.Observable<[Result]> {
map { try $0.map(transform) }
}
}
然后像这样使用扩展名:
func sample2Code(actionSubject: Observable<Void>, disposeBag: DisposeBag) {
actionSubject
.flatMapLatest { fetch() }
.mapArray { DataForUI(serverData: $0) }
.bind(to: resultData)
.disposed(by: disposeBag)
}
或无点版本:
func sample3Code(actionSubject: Observable<Void>, disposeBag: DisposeBag) {
actionSubject
.flatMapLatest(fetch)
.mapArray(DataForUI.init(serverData:))
.bind(to: resultData)
.disposed(by: disposeBag)
}
推荐阅读
- c++ - Operator<< 不返回对象内容
- r - 取消选中框,但可以重新选中 R Shiny
- bash - FFMPEG,任何视频到 16:9
- css - 当我在我的 api 路由中添加斜杠时,一些 css 出错了
- kubernetes - Ingress 每隔几秒就会进行一次健康检查就绪探测
- python - 解析 Google 字体 METADATA.pb - google.protobuf.message.DecodeError:解析消息时出错
- javascript - Bitfinex REST API:如何在一个脚本中检查活动订单直到活动,然后在执行或取消后检查历史订单?
- javascript - ng-click 在javascript数据表中不起作用如何从数据表调用角度控制器中的函数
- javascript - 没有使用 javascript 创建 excel 文件
- apache-spark - Spark Structured Streaming 忽略旧记录