RxSwift和MVVM:可观察到的不在没有绑定的情况下执行

RxSwift和MVVM:可观察到的不在没有绑定的情况下执行,swift,mvvm,rx-swift,Swift,Mvvm,Rx Swift,我是RxSwift新手,正在尝试使用MVVM架构实现该应用程序。我有一个视图模型: class CategoriesViewModel { fileprivate let api: APIService fileprivate let database: DatabaseService let categories: Results<Category> // Input let actionRequest = PublishSubject<Void>() // O

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

}
但如果我对绑定进行注释,则数据库更新部分将停止执行。我需要在视图模型中不使用dispose bag的情况下执行它。可能吗

还有一个小问题:我应该像在我的视图模型代码中那样使用
api
/
database
返回Observable.empty()
弱-强舞蹈,还是可以安全地使用
无主api
/
无主数据库

谢谢

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) })
}
func-mappedarayobservable(来自请求:MappableRequest)->Observable{
让jsonArray=SessionManager.jsonArrayObservable(with:request.urlRequest,isSecured:request.isSecured)
返回jsonArray.mapResponse(在:mappingScheduler,{Mapper().mapArray(jsonArray:$0)}
}

除非有订户准备好接收结果,否则工作不会完成

您的数据库服务中需要有一个dispose包,并订阅可观察的
。比如:

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()
}
class ProductionDatabase:DatabaseService{
var categories更新:可观察{返回_categories}
func updateObservable(具有类别:Observable){
类别
.subscribe(onNext:{[弱自我]类别
//那就去商店吧
self?\u categories.onNext()
})
.处置(由:袋)
}
私人出租_categories=PublishSubject()
私人出租包=处置包()
}

然后
apisccess=database.categoriesUpdated
database.updateObservable(with:requestResult.map{$0.element}.filterNil())

谢谢!但是我可以在订阅时使用
无主self
而不是
[弱self]
?似乎在
self
去初始化后无法调用
self
拥有的
disposeBag
订阅,但我不确定。或者subscribe块是否可以开始执行,在后台保存工作,并在解除分配后到达
self?\u categories.onNext()
?仅使用
unowned
如果您知道self将在程序的生命周期内存在,您知道subscribe将只被调用一次,或者subscribe闭包正在执行将导致删除
self
的操作,否则请使用
weak
。顺便说一句,您也可以使用
APIService
执行上述操作,那么您的视图模型将只包含逻辑。您的意思是我应该在api服务中订阅
actionRequest
,并从基础主题返回对象,就像在数据库示例中一样?但是我有一个返回observable的通用函数(见更新的答案),如果我从同一个
APIService
实例执行两个返回类型不同的请求,我不清楚它将如何工作,如果将
PublishSubject
实例传递到带有observable的服务方法中,并调用
onNext(:)
而不是使用像
private let\u categories=PublishSubject()这样的属性。因此,编译器将推断返回类型,每个订阅都将有自己的主题进行通知。我要说的是,您只提到模型的一个输入,但您也有来自api服务和数据库的输入。将它们建模为第一类输入,而不是将它们埋在平面图中,这将是有帮助的。如何(或如果)你想这样做取决于你。
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()
}