10

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

私が行ったことは、変数のサブジェクトを作成し、モデルがこれをリッスンできるようにすることです。解析サービス:

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

きのこライブラリモデル:

_ = 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)
    })

同期状態を表現するために同じことを行います。

解析サービス:

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

同期ビューモデル:

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

とにかく、これが良い方法なのか、それとも RxSwift を誤用しているのか (そして、これをどのように行うべきかを教えてくれる) かどうかを誰かに教えていただければ幸いです。

乾杯!

4

1 に答える 1

7

うーん...変数の使用に関する記事は次のとおりです (変数は 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 が呼び出されてマッシュルームが取得され、キャッシュされるという考え方です。それ以降は、以前にキャッシュされたキノコのみが返されます。

于 2016-02-23T16:18:15.607 に答える