web-dev-qa-db-ja.com

変数を正しく使用するRxSwift

RxSwiftとMVVMを使用するようにプロジェクトを変換しようとしています。アプリの起動ごとにParseからのデータのリストを同期するサービスがあり、基本的に正しいアプローチを取っていることを確認したいと思います。

私が行ったことは、可変サブジェクトになり、モデルがこれを聞くことができるようにします。 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())

次に、変数alaを更新します

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を誤用している場合(そして私がこれをどのように行うべきかについて私に案内してくれるかどうか)誰かが私に教えてくれれば幸いです。

乾杯!

10
Manny

うーん...これはVariableの使用に関する記事です(VariableはBehaviorSubjectのラッパーであることに注意してください)。

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

あなたの場合、あなたはすでにコールドオブザーバブル(ネットワークコール)を持っているので、サブジェクト/変数は必要ありません。あなたがする必要があるのは、あなたがすでに持っているオブザーバブルを公開し、replay(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を呼び出してキノコを取り出し、キャッシュするという考え方です。それ以降は、以前に現金化されたキノコが返されます。

7
Daniel T.