RxSwift正确使用变量

RxSwift正确使用变量,swift,mvvm,architecture,rx-swift,Swift,Mvvm,Architecture,Rx Swift,我正在尝试将一个项目转换为使用RxSwift和MVVM。我有一项服务,在每次应用程序启动时同步来自Parse的数据列表,我基本上希望确保我采取了正确的方法 我所做的是把它变成一个可变的主题,然后让我的模型听这个。 解析服务: let rx_parseMushrooms = Variable<[ParseMushroom]>([]) struct SyncState { enum State { case Unsynced, ConnectingToServe

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

我所做的是把它变成一个可变的主题,然后让我的模型听这个。 解析服务:

let rx_parseMushrooms = Variable<[ParseMushroom]>([])
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())
然后我更新变量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
          }
      }
无论如何,如果有人能告诉我这是一种很好的方法,还是我滥用了RxSwift(并指导我应该如何做),我将不胜感激


干杯

嗯。。。下面是一篇关于使用变量的文章(请注意,变量是BehaviorSubject的包装器)

在你的例子中,你已经有了一个冷可观察的(网络调用),所以你不需要一个主题/变量。您所需要做的就是发布您已经拥有的可观察对象,并使用replay(1)缓存该值。我希望有一个名为
ParseServer
的类,它包含一个名为
musts
的计算属性

为了帮助将蘑菇从解析中解救出来,您可以使用以下方法(这将创建您需要的冷可观察对象):

扩展查询{
var rx_FindObject:可观察{
返回可观察的。在中创建{observer
self.findObjectsInBackgroundWithBlock({results,中有错误
如果让结果=结果{
观察员:在(.Next(results))
观察员。在(.Completed)
}
否则{
观察者打开(.Error(Error??RxError.Unknown))
}
})
返回匿名({self.cancel()})
}
}
}
然后你会有这样的东西:

class ParseServer {
    var mushrooms: Observable<[Mushroom]> {
        return PFQuery(className: "Mushroom").rx_findObjects
        .map { $0.map { Mushroom(pfObject: $0) } }
        .publish()
        .replay(1)
    }
}
类解析服务器{
可见的{
返回PFQuery(类名:“蘑菇”).rx_findObjects
.map{$0.map{蘑菇(pfObject:$0)}
.publish()
.重播(1)
}
}
我认为以上是正确的。我没有通过编译器运行它,更不用说测试了。它可能需要编辑


不过,我们的想法是,当您第一次调用myParseServer.蘑菇时,系统将调用Parse将蘑菇取出并缓存它们。从那时起,它将只返回以前的现金蘑菇。

太棒了,谢谢你的回复:)同步状态部分呢?基本上,我有一个服务类,它在库同步之前做很多事情。这个“syncLibrary()”方法在应用程序启动时被调用,但我希望几个类能够侦听同步状态,以防新的蘑菇可用。我还有一个初始屏幕,显示同步的进度。您是否也将syncLibrary设置为var?顺便说一句,这是一个应用程序,它能更好地解释我所做的事情。gl/xJaV0d它已经出来了。我只是想掌握RxSwift它一直让我神魂颠倒。看起来很酷的应用程序。就像我引用的那篇文章所说的,你很少需要主题(包括变量)。我认为它们主要在库中,当你有一些东西,例如,接受委托而不是回调,你想将其转换为rx流。在同步的情况下,您的DB代码应该已经被包装好,以便它返回可观察的数据。有点像我在上面为PFObject所做的。主体是用来从无到有地产生热的可观察物的。你的数据库不应该产生热的观测值。是的。我想我仍然在思考热与冷的观测结果。这是有道理的。再次感谢,这是一个简单的想法。当您订阅一个热的可观察对象时,它所做的只是将该观察者添加到其观察者列表中。当您订阅一个冷可观察对象时,它会将该观察者添加到列表中,并启动某种过程。例如,上面代码中的UIButton.rx_tap是热的,PFQuery.rx_findObjects是冷的(每个订阅都会进行一个新的服务器调用)
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)
    }
}