2016-01-08 66 views
10

我正在尝试将项目转换为使用RxSwift和MVVM。我有一项服务,可以在每次启动应用程序时同步来自Parse的数据列表,并且我基本上要确保采取正确的方法。RxSwift正确使用变量

我所做的是做了一个变量主题,然后让我的模型听这个。 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) 
    }) 

我做表达同步状态相同。

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()) 

我再更新变量一拉

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 
      } 
     } 

不管怎样,我将不胜感激,如果有人可以告诉我,如果是这样的一个很好的方法去解决它,或者如果我滥用RxSwift(并指导我如何做这件事s ...)

干杯!

回答

7

嗯......下面是关于使用可变的文章(请注意,变量是围绕BehaviorSubject的包装。)

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

在你的情况,你已经有一个冷观察到的(网络电话, )所以你不需要主题/变量。所有你需要做的就是发布你已有的observable,并使用重放(1)来缓存该值。我期望一个名为ParseServer的类包含一个名为mushrooms的计算属性。

为了帮助蘑菇了解析,你可以使用这个(这将创建冷观察的需要):

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() }) 
     } 
    } 

} 

然后你会碰到这样的:

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

我认为以上是正确的。我没有通过编译器运行它,更不用说测试它了。它可能需要编辑。

这个想法虽然是第一次打电话给myParseServer.mushrooms系统会调用Parse来取出蘑菇并缓存它们。从那时起,它只会返回以前的兑现蘑菇。

+0

真棒,感谢您的回复:)对于同步状态部分呢?基本上我有一个服务类,直到图书馆同步,做了一堆东西。这个“syncLibrary()”方法在应用程序启动时被调用,但我希望有几个类能够在新蘑菇变得可用的情况下收听同步状态。我还有我显示同步进度的初始屏幕。你会不会让syncLibrary变种?这是应用程序顺便说一句,以防它更好地解释我做了什么goo.gl/xJaV0d它已经出来了我只是想要掌握RxSwift它一直在吹我的心.. – Manny

+0

酷的应用程序。就像我引用的文章所说的,你很少需要主体(包括变量)。我认为他们主要在图书馆的那些时候,当你有一些例如需要委托而不是回叫的时候,并且你想将它转换为rx流。 –

+0

在同步的情况下,您的DB代码应该已经被封装,以便它返回observables。有点像我上面为PFObject所做的。受试者从无到有产生热的可观察物。你的数据库不应该产生热的observables。 –