有没有办法简化数据转换?

Is there a way to simplify data trasforming?

有一个函数从服务器调用 API 到 return 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 \([=10=].name)”, displayScore: “convert \([=10=].score)”)
    })
  }
  .bind(to: resultData)
  .disposed(by: disposeBag)

你有很多不同的选择...

首先,我会做一个扩展来处理实际的转换:

extension DataForUI {
    init(serverData: DataFromServer) {
        displayName = "convert \(serverData.name)"
        displayScore = "convert \(serverData.score)"
    }
}

那么你可以 map/map:

func sampleCode(actionSubject: Observable<Void>, disposeBag: DisposeBag) {
    actionSubject
        .flatMapLatest { fetch() }
        .map { [=11=].map { DataForUI(serverData: [=11=]) } }
        .bind(to: resultData)
        .disposed(by: disposeBag)
}

这是相同的想法,但传入的是 init 方法而不是闭包:

func sample1Code(actionSubject: Observable<Void>, disposeBag: DisposeBag) {
    actionSubject
        .flatMapLatest { fetch() }
        .map { [=12=].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 [=13=].map(transform) }
    }
}

然后像这样使用扩展名:

func sample2Code(actionSubject: Observable<Void>, disposeBag: DisposeBag) {
    actionSubject
        .flatMapLatest { fetch() }
        .mapArray { DataForUI(serverData: [=14=]) }
        .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)
}