Как наблюдать верхние Observables с flatMap в RxSwift? - PullRequest
1 голос
/ 06 февраля 2020

Различия между map и flatMap из RxSwift объяснены здесь . Теперь я хочу наблюдать верхний наблюдаемый случай, когда изменения происходят с его внутренней наблюдаемой. Как я могу это сделать?

Давайте рассмотрим пример,

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 { $0.score.asObservable() }
        .subscribe(onNext: { print($0) })
        .disposed(by: bag)

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

В этом примере выше вывод:

80
100

как ожидается. Но я хочу знать полный статус объекта Player (т.е. age игрока) внутри блока подписки .subscribe(onNext: { print($0) }), но он получает только score. Как я могу это сделать?

Мой ожидаемый результат:

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

Ответы [ 2 ]

2 голосов
/ 06 февраля 2020

Другим вариантом будет:

player.asObservable()
    .flatMap { Observable.combineLatest(Observable.just($0.age), $0.score.asObservable()) }

С точки зрения теории категорий, это считается более чистым подходом (вы «поднимаете» значение возраста в монаду), но YMMV.

Кроме того, предметы никогда не должны удерживаться в var, они всегда должны быть let с. Нет смысла заменять тему другим.

В долгосрочной перспективе, вероятно, было бы лучше удалить тему из вашей структуры Player и просто сделать ее:

struct Player {
    var age: Int
    var score: Int
}
1 голос
/ 06 февраля 2020

Вы возвращаете наблюдаемое количество баллов от flatMap, так что ниже по течению доступна только оценка. Вместо этого вы хотите вернуть наблюдаемую информацию об игроке. Вы можете прикрепить возраст к баллу, используя дополнительный оператор map и закрывая аргумент игрока:

player.asObservable()
      .flatMap { p in
          p.score.asObservable()
                 .map { score in (age: p.age, score: p.score) } }
      .subscribe(onNext: { print($0) })
      .disposed(by: bag)
...