RxSwift 和 MVVM:observable 在没有绑定的情况下无法执行

Posted

技术标签:

【中文标题】RxSwift 和 MVVM:observable 在没有绑定的情况下无法执行【英文标题】:RxSwift and MVVM: observable not executing without binding 【发布时间】:2017-09-18 18:24:32 【问题描述】:

我是 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()



我在视图控制器中有以下绑定:

   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

谢谢。

更新:

APIService 中返回 observable 的函数:

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&lt;[Category]&gt;。比如:

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())

【讨论】:

谢谢!但是我可以在订阅时使用unowned self 而不是[weak self] 吗?似乎订阅 self 拥有的 disposeBagself 取消初始化后无法调用,但我不确定。或者可以订阅块开始执行,在后台保存工作,并在self 被释放后到达self?._categories.onNext() 只使用unowned,如果你知道self将在程序的生命周期中存在,你知道订阅只会被调用一次,或者订阅闭包正在做一些会导致@987654333的事情@要删除,否则使用weak。顺便说一句,您也可以使用 APIService 执行上述操作,然后您的视图模型将只包含逻辑。 你的意思是我应该订阅 api 服务中的actionRequest 并从基础主题返回对象,就像在数据库示例中一样?但是我有返回 observable 的通用函数(见更新的答案),我不清楚如果我将从 APIService 的同一实例中执行两个具有不同返回类型的请求,它将如何工作@ 如果将 PublishSubject 实例传递给具有 observable 的服务方法并在其上调用 onNext(:_) 而不是使用像 private let _categories = PublishSubject&lt;Void&gt;() 这样的属性,它将起作用。所以编译器会推断返回类型,每个订阅都会有自己的主题通知。 我想说的是,您只提到了模型的一个输入,但您也有来自 api 服务和数据库的输入。将它们建模为第一类输入而不是将它们埋在 flatMaps 中会很有帮助。如何(或是否)你想这样做取决于你。

以上是关于RxSwift 和 MVVM:observable 在没有绑定的情况下无法执行的主要内容,如果未能解决你的问题,请参考以下文章

RxSwift:多次连接到 Connectable Observable

RxSwift 从 Observable 序列中的一项获取值

删除项目 RxSwift MVVM 模式

传递数据 MVVM 和 RxSwift

从其他 Observable 获取值的 Rx Observable

Observable 的 RxSwift 用途