2016-03-17 3 views
5

У меня есть переменная, которая представляет собой массив значений перечисления. Эти значения меняются со временем.Наблюдаемое текущее и предыдущее значение

enum Option { 
    case One 
    case Two 
    case Three 
} 

let options = Variable<[Option]>([ .One, .Two, .Three ]) 

Затем я наблюдаю эту переменную для изменений. Проблема в том, что мне нужно знать разницу между самым новым значением и предыдущим значением. Я сейчас делаю это:

let previousOptions: [Option] = [ .One, .Two, .Three ] 

... 

options 
    .asObservable() 
    .subscribeNext { [unowned self] opts in 
     // Do some work diff'ing previousOptions and opt 
     // .... 
     self.previousOptions = opts 
    } 

Есть ли что-то встроенное для RxSwift, которое бы справилось с этим лучше? Есть ли способ всегда получать предыдущие и текущие значения из сигнала?

ответ

5

там вы идете

options.asObservable() 
    .scan([ [],[] ]) { seed, newValue in 
     return [ seed[1], newValue ] 
    } 
    // optional, working with tuple of array is better than array of array 
    .map { array in (array[0], array[1]) } 
    //optional, in case you dont want empty array 
    .skipWhile { $0.count == 0 && $1.count == 0 } 

вернет Observable<([Options], [Options])> :)

3

Как сказал Фам Хоан, scan(_) является правильным инструментом для работы. Марин Тодоров написал good post, выполнив именно это.

Вот что я придумал, основанный на пост Марин:

options 
     .asObservable() 
     .scan([]) { 
      (previous, current) in 
       return Array(previous + [current]).suffix(2) 
     } 
     .subscribeNext { 
      (lastTwoOptions) in 
       let previousOptions = lastTwoOptions.first 
       let currentOptions = lastTwoOptions.last 
       // Do your thing. Remember to check for nil the first time around! 
     } 
     .addDisposableTo(self.disposeBag) 

Надежда, что помогает

5

Вот удобный родовое расширение, которое должно охватывать эти «Я хочу, предыдущий и ток значение»случаи использования:

extension ObservableType { 

    func withPrevious(startWith first: E) -> Observable<(E, E)> { 
     return scan((first, first)) { ($0.1, $1) }.skip(1) 
    } 
} 
0

Я хотел бы предложить что-то вроде этого (для будущих посетителей):

options.asObservable() 
     .map { (old: [], new: $0) } // change type from array to tuple 
     .scan((old: [], new: [])) { previous, current in 
      // seed with an empty tuple & return both information 
      return (old: previous.new, new: current.new) 
     } 
     .subscribe(onNext: { option in 
      let oldArray = option.old // old 
      let newArray = option.new // new 
     } 
     .addDisposableTo(disposeBag) 
Смежные вопросы