RxSwift和MVVM:可观察到的不在没有绑定的情况下执行
我是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
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()
}