2017-09-18 67 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'的相同实例 –