2017-09-18 10 views
0

私はRxSwiftを初めて使い、MVVMアーキテクチャを使ってアプリケーションを実装しようとしています。私は、ビューモデルがあります:RxSwiftとMVVM:観測なしバインディングなしで実行しない

class CategoriesViewModel { 

fileprivate let api: APIService 
fileprivate let database: DatabaseService 

let categories: Results<Category> 

// Input 
let actionRequest = PublishSubject<Void>() 

// Output 
let changeset: Observable<(AnyRealmCollection<Category>, RealmChangeset?)> 
let apiSuccess: Observable<Void> 
let apiFailure: Observable<Error> 

init(api: APIService, database: DatabaseService) { 
    self.api = api 
    self.database = database 

    categories = database.realm.objects(Category.self).sorted(byKeyPath: Category.KeyPath.name) 

    changeset = Observable.changeset(from: categories) 

    let requestResult = actionRequest 
     .flatMapLatest { [weak api] _ -> Observable<Event<[Category]>> in 
      guard let strongAPI = api else { 
       return Observable.empty() 
      } 

      let request = APIService.MappableRequest(Category.self, resource: .categories) 
      return strongAPI.mappedArrayObservable(from: request).materialize() 
     } 
     .shareReplayLatestWhileConnected() 

    apiSuccess = requestResult 
     .map { $0.element } 
     .filterNil() 
     .flatMapLatest { [weak database] newObjects -> Observable<Void> in 
      guard let strongDatabase = database else { 
       return Observable.empty() 
      } 

      return strongDatabase.updateObservable(with: newObjects) 
     } 

    apiFailure = requestResult 
     .map { $0.error } 
     .filterNil() 
} 

} 

を、私は、ビューコントローラで、次のbingindsあります

viewModel.apiSuccess 
     .map { _ in false } 
     .bind(to: refreshControl.rx.isRefreshing) 
     .disposed(by: disposeBag) 

    viewModel.apiFailure 
     .map { _ in false } 
     .bind(to: refreshControl.rx.isRefreshing) 
     .disposed(by: disposeBag) 

をしかし、私はバインディングコメント場合は、データベースの更新を持つ部分が実行を停止します。ビューモデルでdispose bagを使わずに、私はそれをとにかく実行させる必要があります。出来ますか?

そして、少し追加の質問:私は私のビューモデルのコードのようにapi/databasereturn Observable.empty()で弱い強いダンスを使うべきか、私は無事unowned api/unowned databaseを使用することができますか?

ありがとうございました。

UPD:APIServiceで観察復帰のための

機能:結果を受け取るために用意した加入者がある場合を除き

func mappedArrayObservable<T>(from request: MappableRequest<T>) -> Observable<[T]> { 
    let jsonArray = SessionManager.jsonArrayObservable(with: request.urlRequest, isSecured: request.isSecured) 
    return jsonArray.mapResponse(on: mappingSheduler, { Mapper<T>().mapArray(JSONArray: $0) }) 
} 

答えて

1

作業が行われません。

DatabaseServiceには、処分袋があり、Observable<[Category]>に登録する必要があります。何かのように:次に

class ProductionDatabase: DatabaseService { 

    var categoriesUpdated: Observable<Void> { return _categories } 

    func updateObservable(with categories: Observable<[Category]>) { 
     categories 
      .subscribe(onNext: { [weak self] categories in 
       // store categories an then 
       self?._categories.onNext() 
      }) 
      .disposed(by: bag) 
    } 

    private let _categories = PublishSubject<Void>() 
    private let bag = DisposeBag() 
} 

apiSuccess = database.categoriesUpdateddatabase.updateObservable(with: requestResult.map { $0.element }.filterNil())

+0

ありがとう!しかし、サブスクライブで「弱い自己」の代わりに「無所属の自己」を使うことはできますか? 'self'によって所有されている' disposeBag'を購読することは、 'self'初期化の後に呼び出すことはできませんが、わかりません。または、ブロックの実行を開始し、バックグラウンドで作業を保存し、 'self?_ categories.onNext()'に到達することができます。 –

+1

プログラムの終了時に自己が存在することがわかっている場合にのみ 'unowned'を使います。サブスクライブは一度だけ呼び出されるか、サブスクライブクローズは' self'が削除される何かをしていることを知っています。弱いところで、あなたは 'APIService'で上記を行うこともできます。そうすれば、あなたのビューモデルにはロジックだけが含まれます。 –

+0

apiサービスで 'actionRequest'を購読し、データベースの例のように、基礎となるサブジェクトからオブジェクトを返すべきですか?しかし、私は監視可能な戻り値を持つ汎用関数を持っています(更新された答えを参照してください)、 'APIService'の同じインスタンスから別の戻り値の型を持つ2つの要求を行うとどうなるかは分かりません –

関連する問題