gpt4 book ai didi

ios - MVVM 与 RxSwift

转载 作者:行者123 更新时间:2023-11-30 11:32:46 25 4
gpt4 key购买 nike

我试图理解 mvvm + RxSwift,但我有一些问题。

我目前正在使用这种方法,我不确定它是否正确或可以更好。我该如何对方法进行分组,我的意思是,也许像 doFirst(loading = true).doNext(getData).doLast(loading = false).catch(apiError) 这样的东西,然后订阅此事件?这可能吗?

View Controller :

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

viewModel = UsersViewModel(apiService: apiService)
configureBindings()
}

func configureBindings() {

tableView.delegate = nil
tableView.dataSource = nil

viewModel.isLoading.bind(to: loadingView.rx.isAnimating)
.disposed(by: disposeBag)

viewModel.models
.bind(to: tableView.rx.items(cellIdentifier: "userCell", cellType: UserCell.self)) {(_, _, cell) in
print("Binding the cell items")
}.disposed(by: disposeBag)

tableView.rx.modelSelected(User.self).subscribe(onNext: { value in
print(value)
}).disposed(by: disposeBag)

viewModel.error.filterNil().subscribe(onNext: { (err) in
self.tableView.backgroundView = EmptyView(title: "No Users", description: "No users found")
print("Showing empty view...")
print(err)
}).disposed(by: disposeBag)
}
}

然后在我的 UsersViewModel 中:

class UsersViewModel {

var models: Observable<[User]> {
return modelsVariable.asObservable()
}

var isLoading: Observable<Bool> {
return isLoadingVariable.asObservable()
}

var error: Observable<ApiError?> {
return errorVariable.asObservable()
}

private var modelsVariable = BehaviorRelay<[User]>(value: [])
private var isLoadingVariable = BehaviorRelay<Bool>(value: false)
private var errorVariable = BehaviorRelay<ApiError?>(value: nil)

// MARK: - Data Manager
var apiService: API

required init(apiService: API) {
self.apiService = apiService

isLoadingVariable.accept(true)

apiService.GET(EndPoints.USER_LIST, type: Several<User>.self)
.subscribe(onNext: { (model) in
self.isLoadingVariable.accept(false)
self.modelsVariable.accept(model.items)
}, onError: { (err) in
self.isLoadingVariable.accept(false)
self.errorVariable.accept(err as? ApiError)
})
}
}

我的“GET”函数仅返回 Observable<Several<User>>.

几个:

struct Several {
var items: [User]
}

我可以做哪些改进吗?

最佳答案

有点难以理解您的要求,但如果您担心 init 方法的命令性性质,并且希望将 API 调用包装到连续的 Observable 序列中,可以重复,你可以这样做:

class UsersViewModel {

//...

var fetchUsersObserver: AnyObserver<Void> {
return fetchUsersSubject.asObserver()
}

//...

private let fetchUsersSubject = PublishSubject<Void>()
private let disposeBag = DisposeBag()

//...

required init(apiService: API) {
self.apiService = apiService
bindFetchUsers()
}

private func bindFetchUsers() {
fetchUsersSubject
.asObservable()
.do(onNext: { [weak self] _ in self?.isLoadingVariable.accept(true) })
.flatMap(self.fetchUsers)
.do(onNext: { [weak self] _ in self?.isLoadingVariable.accept(false) })
.bind(to: modelsVariable)
.disposed(by: disposeBag)
}

private func fetchUsers() -> Observable<[User]> {
return apiService
.GET(EndPoints.USER_LIST, type: Several<User>.self)
.map { $0.items }
.catchError { [weak self] error in
self?.errorVariable.accept(error as? ApiError)
return .just([])
}
}
}

然后,您只需将一个控件绑定(bind)到此AnyObserver,或者手动向其发送事件:

func configureBindings() {
// from a control, such as UIButton
someButton
.rx
.tap
.bind(to: viewModel.fetchUsersObserver)
.disposed(by: disposeBag)

// manually
viewModel.fetchUsersObserver.onNext(())
}

脚注 1: 我通常喜欢将 View 模型设为 struct,这样我就不必担心所有 [weak self] 语句。

脚注 2: 注意 fetchUsers() 函数如何捕获抛出的任何错误,并且不会让错误传播到外部 Observable 序列。这很重要,因为如果这个外部 Observable 发出 error 事件,它就永远不会发出另一个 next 事件。

关于ios - MVVM 与 RxSwift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50084692/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com