如何查看Variable<...>
中RxSwift
类内Variable
值(ViewModel
ViewController
的变化?
因此,如果我在Variable<..>
中拥有的ViewModel
的任何值在ViewModel
中发生的事情内发生变化,那么ViewController
将会被注意到“嘿!ViewModel中的一个或多个Variable <..>已更改!向ViewModel询问更新UI和更新UI所需的数据!“
然后ViewController
在ViewController内调用方法updateUI()
,并在其中向ViewModel
询问状态/状态之类的所有信息以更新UI,例如:>
func updateUI() {
progressBar.hide = viewModel.getProgressBarVisibility()
errorMessageLabel.hide = viewModel.getErrorMessageVisibility()
errorMessageLabel.text = viewModel.getErrorMessageText()
.....
...
}
答案 0 :(得分:0)
如果单个ViewModel的属性值更改,为什么要更新完整的UI?
RxSwift使您能够独立聆听更改,并且可以相应地响应/更改UI。
在我看来,这是您的ViewModel和ViewController类的外观:
class ViewModel {
private var progressBarVisibiity:Variable<Double> = Variable.init(0.0)
private var errorMessageVisibiity:Variable<Double> = Variable.init(0.0)
private var errorMessageLabel:Variable<String> = Variable.init("Default text")
public func setProgressBarVisibiity(_ value:Double) {
progressBarVisibiity.value = value
}
public func setErrorMessageVisibiity(_ value:Double) {
errorMessageVisibiity.value = value
}
public func setErrorMessageLabel(_ value:String) {
errorMessageLabel.value = value
}
public func observeProgressBarVisibiity() -> Observable<Double> {
return progressBarVisibiity.asObservable().observeOn(MainScheduler())
}
public func observeErrorMessageVisibiity() -> Observable<Double> {
return errorMessageVisibiity.asObservable().observeOn(MainScheduler())
}
public func observeErrorMessageLabel() -> Observable<String> {
return errorMessageLabel.asObservable().observeOn(MainScheduler())
}
}
class ViewController {
let viewModel = ViewModel()
let disposeBag = DisposeBag()
func observeViewModelChanges() {
viewModel
.observeProgressBarVisibiity()
.subscribe(onNext: { value in
self.progressBar.hide = viewModel.getProgressBarVisibility()
})
.disposed(by: disposeBag)
viewModel
.observeErrorMessageVisibiity()
.subscribe(onNext: { value in
self.errorMessageLabel.hide = value
})
.disposed(by: disposeBag)
viewModel
.observeErrorMessageLabel()
.subscribe(onNext: { value in
self.errorMessageLabel.text = value
})
.disposed(by: disposeBag)
}
}
答案 1 :(得分:0)
要更新您的UI,我建议使用一个viewState
变量,您可以根据需要在视图模型类中对其进行更新,例如:
/// Making it generic allow you to add your view specific state
public enum ViewState<T> {
// add all the case you need
case loading
case ready(T)
case failure(Error)
}
然后在您的viewModel类中:
let viewState: Variable<ViewState<YourViewControllerState>> = Variable<ViewState<YourViewControllerState>>(.loading)
其中YourViewControllerState是具有特定情况的枚举:
enum YourViewControllerState {
case progressBarShowed, //...
}
最后在您的ViewController中:
viewModel.viewState
.asObservable()
.observeOn(MainScheduler.instance)
.subscribe { [weak self] _ in
self?.updateUI()
}.disposed(by: disposeBag)
private func updateUI() {
guard isViewLoaded else {
return
}
switch viewModel.viewState.value {
case .ready(.progressBarShowed):
progressBar.hide = viewModel.getProgressBarVisibility()
case .failure:
errorMessageLabel.hide = viewModel.getErrorMessageVisibility()
errorMessageLabel.text = viewModel.getErrorMessageText()
}
}
答案 2 :(得分:0)
我们可以构造一个双向绑定运算符,您可以只使用bindTo。这是ControlProperty <->变量和变量<->变量的实现:
infix operator <->
@discardableResult func <-><T>(property: ControlProperty<T>, variable: BehaviorSubject<T>) -> Disposable {
let variableToProperty = variable.asObservable()
.bind(to: property)
let propertyToVariable = property
.subscribe(
onNext: { variable.onNext($0) },
onCompleted: { variableToProperty.dispose() }
)
return Disposables.create(variableToProperty, propertyToVariable)
}
您可以在以下文章中找到问题的详细答案。 Two way binding in RxSwift