如何在 RxSwift 中使用 flatMap 观察上层 Observables?

How to observe upper Observables with flatMap in RxSwift?

RxSwiftmapflatMap 之间的区别已经解释 。现在我想在内部可观察对象发生变化时观察上层可观察实例。 我该怎么做?

让我们看例子,

func testFlatMap() {

    let bag = DisposeBag()

    struct Player {
        var age: Int
        var score: BehaviorSubject<Int>
    }

    let male = Player(age: 28, score: BehaviorSubject(value: 80))

    let player = PublishSubject<Player>()

    player.asObservable()
        .flatMap { [=10=].score.asObservable() }
        .subscribe(onNext: { print([=10=]) })
        .disposed(by: bag)

    player.on(.next(male))
    male.score.on(.next(100))
}

在上面的例子中,输出是,

80
100

符合预期。但我想知道订阅块 .subscribe(onNext: { print([=17=]) }) 内的完整玩家对象状态(即玩家的 age),但它只获得 score我该怎么做?

我的预期输出是,

Player (where I can access both age:28 and score:80)
Player (where I can access both age:28 and score:100)

您 return 从 flatMap 中观察分数,因此只有一个分数可用于下游。相反,您想要 return 可观察到的玩家信息。您可以通过使用额外的 map 运算符并关闭玩家参数来将年龄附加到分数:

player.asObservable()
      .flatMap { p in
          p.score.asObservable()
                 .map { score in (age: p.age, score: p.score) } }
      .subscribe(onNext: { print([=10=]) })
      .disposed(by: bag)

另一种选择是:

player.asObservable()
    .flatMap { Observable.combineLatest(Observable.just([=10=].age), [=10=].score.asObservable()) }

从类别理论 POV 来看,这被认为是一种更简洁的方法(您将 "lifting" 年龄值放入 monad,)但是 YMMV。

另外,Subjects 不应该被保存在 var,它们应该总是 lets。用不同的主题替换主题是没有意义的。

从您的 Player 结构体中移除主题并使其成为:

可能会更好 运行
struct Player {
    var age: Int
    var score: Int
}