2016-05-25 4 views
1

In meinem OS X Statusleiste App neu zu starten ich interval Funktion bin mit periodisch einen externen API aufrufen und das Ergebnis anzeigen:korrekte Art und Weise beobachtbar Intervall in RxSwift

Observable<Int> 
    .interval(120.0, scheduler: MainScheduler.instance) 
    .startWith(-1) // to start immediately 
    .flatMapLatest(makeRequest) // makeRequest is (dummy: Int) -> Observable<SummaryResponse?> 
    .subscribeNext(setSummary) 
    .addDisposableTo(disposeBag) 

Wenn jedoch Benutzer die Einstellungen ändert sich in In der Zwischenzeit möchte ich dieses Intervall "neu starten" und sofort einen neuen Anruf tätigen, um die Änderungen widerzuspiegeln (ohne auf den nächsten Anruf warten zu müssen).

Was ist der beste Weg, dies zu tun?

  1. Shop die beobachtbare als Eigenschaft und setzen Sie ihn auf nil oder .dispose() auf nennen (oder beides) und eine neue beobachtbaren schaffen?
  2. Setzen Sie disposeBag auf nil und erstellen Sie eine neue Observable?
  3. Irgendein anderer Weg?

Antwort

4

Was Sie suchen, ist merge. Sie haben zwei Observable s, von denen eine interval und die anderen, die Präferenzänderungen darstellt. Sie wollen merge diejenigen in einem Observable mit den Elementen von beiden, sofort wie sie kommen.

, die wie folgt aussehen:

// this should really come from somewhere else in your app 
let preferencesChanged = PublishSubject<Void>() 

// the `map` is so that the element type goes from `Int` to `Void` 
// since the `merge` requires that the element types match 
let timer = Observable<Int>.timer(0, period: 3, scheduler: MainScheduler.instance).map { _ in() } 

Observable.of(timer, preferencesChanged) 
    .merge() 
    .flatMapLatest(makeRequest) 
    .subscribeNext(setSummary) 
    .addDisposableTo(disposeBag) 

Beachten Sie auch, wie ich timer statt interval bin mit, da es uns, wenn zum ersten Mal, wie auch die Zeit für die anschließende Feuer angeben kann, Zündungen. Auf diese Weise brauchen Sie keine . Beide Möglichkeiten funktionieren jedoch. Es ist eine Frage der Präferenz.

Noch eine Sache zu beachten. Dies ist außerhalb des Bereichs Ihrer Frage (und vielleicht hielten Sie es einfach für die Frage) aber statt subscribeNext(setSummary), sollten Sie in Betracht ziehen, das Ergebnis als Observable und stattdessen bindTo oder drive die UI oder DB (oder was auch immer " Zusammenfassung "ist).

+0

Danke für die Antwort und alle Vorschläge! Das Wechseln zu 'timer' und das Zuordnen des Dummy int zu void hat diesen Code viel besser aussehen lassen :). 'setSummary' setzt grundsätzlich' NSStatusItem.title', prüft, ob ich Rx verwenden kann, um damit umzugehen :). –

+0

Aber das bringt wirklich nichts zurück, oder? es gibt nur Ereignisse aus, wenn der Timer bereit ist ODER das andere Observable etwas ausstrahlt, richtig? Ich wäre noch an einer guten Möglichkeit interessiert, das Intervall wirklich zurückzusetzen, wenn das wahr ist. –

+0

Ich verstehe nicht, was Sie meinen. Wir setzen den Timer Observable nicht zurück. Vielmehr wird dieser Timer Observable verwendet Setzen Sie das Observable zurück, das von makeRequest zurückgegeben wurde Es klingt, als wollten Sie etwas anderes als das, wonach diese Frage gefragt wurde. – solidcell