2016-03-17 15 views
5

Mam zmienną, która jest tablicą wartości wyliczeniowych. Te wartości zmieniają się z czasem.Observable Current and Previous Value

enum Option { 
    case One 
    case Two 
    case Three 
} 

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

Obserwuję tę zmienną dla zmian. Problem polega na tym, że muszę znać różnicę między najnowszą wartością a poprzednią wartością. Obecnie robię to:

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

... 

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

Czy jest coś wbudowanego w RxSwift, które poradziłoby sobie z tym lepiej? Czy istnieje sposób, aby zawsze uzyskać sygnał z poprzednich i bieżących wartości?

Odpowiedz

5

tam idziesz

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 } 

powróci Observable<([Options], [Options])> :)

3

Jak powiedział Pham Hoan, scan(_) jest odpowiednim narzędziem do pracy. Marin Todorov napisał właśnie o tym good post.

Oto co wymyśliłem, na podstawie Marin postu:

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) 

nadzieję, że pomoże

5

Oto przydatne rozszerzenie generycznych, które powinny obejmować te „Chcę poprzedni i bieżący wartość”przypadki użytku:

extension ObservableType { 

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

proponuję coś takiego (dla przyszłych użytkowników):

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)