2016-03-17 21 views
5

Ho una variabile che è una matrice di valori enum. Questi valori cambiano nel tempo.Corrente osservabile e valore precedente

enum Option { 
    case One 
    case Two 
    case Three 
} 

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

Osservo quindi questa variabile per le modifiche. Il problema è che ho bisogno di conoscere il diff tra il valore più recente e il valore precedente. Attualmente sto facendo questo:

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

... 

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

C'è qualcosa incorporato in RxSwift che gestirà meglio questo? C'è un modo per ottenere sempre i valori precedenti e attuali da un segnale?

risposta

5

ci si va

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 } 

tornerà Observable<([Options], [Options])> :)

3

Come ha detto Pham Hoan, scan(_) è lo strumento giusto per il lavoro. Marin Todorov ha scritto un good post facendo esattamente questo.

Ecco cosa mi è venuta, sulla base di post di Marin:

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) 

Speranza che aiuta

5

Ecco un'estensione generica a portata di mano, che dovrebbe coprire questi "Voglio che il precedente e l'attuale valore" casi d'uso:

extension ObservableType { 

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

vorrei suggerire qualcosa di simile (per i futuri visitatori):

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) 
Problemi correlati