Подписка на выборку вложенного массива - PullRequest
0 голосов
/ 14 декабря 2018

У меня есть объект и его свойства следующим образом:

class Section {

 var cards: [MemberCard]

 init(card: [MemberCard]) {

 }
}

class MemberCard {
  var name: String
  var address: String?
  init(name: String) {
     self.name = name
  }
}

Я подписываюсь на RxStream типа Observable <[Section]>.Перед подпиской я бы хотел использовать эту функцию на плоской карте.

, где плоская карта будет выполнять следующие действия:

let sectionsStream : Observable<[Section]> = Observable.just([sections])
sectionsStream
.flatMap { [weak self] (sections) -> Observable<[Section]> in
  for section in sections {

     for card in section.cards {

     }
   }
 }.subscribe(onNext: { [weak self] (sections) in

    self?.updateUI(memberSections: sections)

}).disposed(by: disposeBag)

func getAddressFromCache(card: MemberCard) -> Observable<MemberCard> {
   return Cache(id: card.name).flatMap ({ (card) -> Observable<MemberCard> in
      asyncCall{

         return Observable.just(card)   
      }

   }
}

Как будет выглядеть плоская карта при конвертации Observable<[Section]> к массиву [Observable<MemberCard>] и обратно к Observable<[Section]>?

Ответы [ 2 ]

0 голосов
/ 15 декабря 2018

Вот, пожалуйста:

extension ObservableType where E == [Section] {
    func addressedCards() -> Observable<[Section]> {
        return flatMap {
            Observable.combineLatest($0.map { getAddresses($0.cards) })
        }
        .map {
            $0.map { Section(cards: $0) }
        }
    }
}

func getAddresses(_ cards: [MemberCard]) -> Observable<[MemberCard]> {
    return Observable.combineLatest(cards
        .map {
            getAddressFromCache(card: $0)
                .catchErrorJustReturn($0)
        })
}

Если один из кешей выдаст ошибку, приведенное выше вернет членскую карту без изменений.

У меня есть пара других советов.

  • В соответствии с функциональной природой Rx, ваши типы Section и MemberCard должны быть либо структурами, либо (классы с let s вместо var s).
  • Не используйте String?, если у вас нет веской причины, по которой пустая строка ("") отличается от отсутствующей строки (nil).Нет причин, по которым вам нужно проверять существование и isEmpty каждый раз, когда вы хотите узнать, был ли заполнен адрес. (То же самое касается массивов и словарей.)

Для этого кода правильное использование combineLatest является ключом.Он может превратить [Observable<T>] в Observable<[T]>.Узнайте другие интересные способы объединения Observables здесь: https://medium.com/@danielt1263/recipes-for-combining-observables-in-rxswift-ec4f8157265f

0 голосов
/ 14 декабря 2018

Технически, вот так -

let o1: Observable<MemberCard> = ...
let o2: Observable<Section> = omc.toList().map { Section($0) }
let o2: Observable<[Section]> = Observable.concat(o2 /* and all others */).toList()

Но я не думаю, что это оптимальное решение, по крайней мере, потому что нет обработки ошибок для случая, когда не удается извлечь одну или несколько карт.Я бы предпочел построить что-то вокруг агрегации с оператором .scan(), как в https://github.com/maxvol/RaspSwift

...