2017-09-18 69 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) 

但如果我評論的綁定,與數據庫更新部分停止執行。無論如何,我需要使其執行,而不必在視圖模型中使用處理袋。可能嗎?

和小附加的問題:我應該用在我的視圖模型代碼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需要在其中包含一個dispose包並訂閱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' deinitialization之後不能被調用,但我不確定。或者可以訂閱塊開始執行,在後臺保存工作,並在'self'被釋放之後到達'self?._ categories.onNext()'? –

+1

如果你知道程序的生命中將存在self,那麼你只能使用'unowned',你知道訂閱只會被調用一次,或者訂閱閉包正在做一些會導致'self'被刪除的東西,否則使用'weak'。順便說一句,你也可以用'APIService'完成上述操作,那麼你的視圖模型將只包含邏輯。 –

+0

你的意思是我應該在api服務中訂閱'actionRequest'並從底層主題返回對象,就像數據庫中的例子一樣?但我有泛型函數返回observable(見更新的答案),並不清楚它將如何工作,如果我會做兩個不同返回類型的請求,從'APIService'的相同實例 –