2016-01-08 13 views
10

Ich versuche ein Projekt zu konvertieren, RxSwift und MVVM zu verwenden. Ich habe einen Dienst, der bei jedem App-Start eine Liste von Daten von Parse synchronisiert und ich möchte im Grunde sicherstellen, dass ich den richtigen Ansatz nehme.RxSwift Verwenden von Variablen korrekt

Was ich getan habe, ist ein variables Thema gemacht und dann erlauben meine Modelle, dies zu hören. ParseService:

let rx_parseMushrooms = Variable<[ParseMushroom]>([]) 

MushroomLibraryModel:

_ = parseService.rx_parseMushrooms 
    .asObservable() 
    .map { (parseMushrooms:[ParseMushroom]) -> [Mushroom] in 
     let mushrooms = parseMushrooms.map { (parseMushroom:ParseMushroom) -> Mushroom in 
      let mushroom = Mapper<Mushroom>().map(parseMushroom.dictionaryWithValuesForKeys(parseMushroom.allKeys())) 
      return mushroom! 
     } 

     return mushrooms 
    } 
    .subscribeNext({ (mushrooms:[Mushroom]) -> Void in 
     self.mushrooms = mushrooms 
     print(mushrooms) 
    }) 

mache ich das gleiche für den Sync-Zustand ausdrückt.

ParseService:

struct SyncState { 
    enum State { 
     case Unsynced, ConnectingToServer, SyncingInfo, FetchingImageList, SyncingImages, SyncComplete, SyncCompleteWithError 
    } 

    var infoToSync = 0 
    var imagesToSync = 0 
    var imagesSynced = 0 

    var state = State.Unsynced 
} 

let rx_syncState = Variable(SyncState()) 

ich die Variable dann aktualisieren a la

self.rx_syncState.value = self.syncState 

SyncViewModel:

_ = parseService.rx_syncState 
    .asObservable() 
    .subscribeNext { [weak self] (syncState:ParseService.SyncState) -> Void in 
      switch syncState.state { 
       //show stuff based on state struct 
      } 
     } 

Sowieso würde ich mich sehr freuen, wenn mir jemand sagen kann, ob dies der ist ein guter Weg, um es zu tun, oder wenn ich RxSwift missbrauche (und mich führe, wie ich das machen soll s ...)

Prost! Hmm

Antwort

7

... Hier ist ein Artikel über Variable verwenden (beachten Sie, dass Variable ist ein Wrapper um BehaviorSubject.)

http://davesexton.com/blog/post/To-Use-Subject-Or-Not-To-Use-Subject.aspx

In Ihrem Fall bereits eine Erkältung zu beobachten haben (das Netzanruf,) Sie brauchen also keinen Betreff/Variable. Alles, was Sie tun müssen, ist das bereits vorhandene Observable zu veröffentlichen und replay (1) zu verwenden, um den Wert zwischenzuspeichern. Ich würde eine Klasse mit dem Namen ParseServer erwarten, die eine berechnete Eigenschaft mit dem Namen mushrooms enthält.

zu helfen, die Pilze aus Parse zu bekommen, können Sie diese verwenden (dies wird die Kälte zu beobachten Sie benötigen erstellen):

extension PFQuery { 

    var rx_findObjects: Observable<[PFObject]> { 
     return Observable.create { observer in 
      self.findObjectsInBackgroundWithBlock({ results, error in 
       if let results = results { 
        observer.on(.Next(results)) 
        observer.on(.Completed) 
       } 
       else { 
        observer.on(.Error(error ?? RxError.Unknown)) 
       } 
      }) 
      return AnonymousDisposable({ self.cancel() }) 
     } 
    } 

} 

Und dann würden Sie so etwas wie haben:

class ParseServer { 
    var mushrooms: Observable<[Mushroom]> { 
     return PFQuery(className: "Mushroom").rx_findObjects 
     .map { $0.map { Mushroom(pfObject: $0) } } 
     .publish() 
     .replay(1) 
    } 
} 

Ich denke das obige ist richtig. Ich habe es jedoch nicht durch einen Compiler laufen lassen, geschweige denn getestet. Es muss möglicherweise bearbeitet werden.

Die Idee ist jedoch, dass das System beim ersten Aufruf von myParseServer.mushrooms Parse aufrufen wird, um die Pilze herauszuholen und sie zwischenzuspeichern. Von da an wird es nur die vorherigen eingelösten Pilze zurückgeben.

+0

Ehrfürchtig und danke für die Antwort :) Was ist mit dem Synchronisierungsstatus Teil? Im Grunde habe ich eine Service-Klasse, die eine Menge Sachen macht, bis die Bibliothek synchronisiert ist. Diese "syncLibrary()" -Methode wird beim App-Start aufgerufen, aber ich möchte, dass mehrere Klassen den Status der Synchronisierung abhören können, falls neue Pilze verfügbar werden. Ich habe auch den ersten Bildschirm, in dem ich den Fortschritt der Synchronisierung zeige. Würden Sie auch syncLibrary eine var machen? Dies ist die app btw für den Fall, dass es besser erklärt, was ich tun goo.gl/xJaV0d es ist schon raus Ich versuche nur RxSwift zu meistern es hält mir den Kopf .. – Manny

+0

Cool aussehende App.Wie der Artikel, auf den ich referenziere, braucht man selten Subjekte (einschließlich Variable). Ich denke, sie sind hauptsächlich in der Bibliothek für jene Zeiten, wenn Sie etwas haben, das zum Beispiel einen Delegaten anstelle eines Callbacks nimmt und Sie in einen konvertieren möchten RX-Stream. –

+0

Im Fall der Synchronisierung sollte Ihr DB-Code bereits umbrochen sein, damit Observables zurückgegeben werden. Ein bisschen wie das, was ich oben für PFObject getan habe. Die Themen dienen dazu, heiße Observable aus dem Nichts zu generieren. Ihre DB sollte keine heißen Observablen erzeugen. –

Verwandte Themen