我正在基于MVVM编写我的第一个应用程序,并且正在尝试使用Actions,以便可以利用它们似乎有用的一些内置功能。但是,我很难理解如何定义一个依赖于私有ReplaySubject的Action(使我能够“提要:”视图模型)并绑定到视图控制器中文本字段中的值。我可能对自己的解释不够好,但希望代码能清楚说明我要做什么。我似乎找不到许多使用Action的示例,因此指针将非常有帮助
// View model
protocol ObservationViewModelType: ViewModelType { }
final class ObservationsViewModel: ObservationViewModelType {
// MARK:- Protocol conformance
typealias Dependencies = HasSceneCoordinator & HasPatientService
struct Input {
// var patient: AnyObserver<Patient>
}
struct Output {
let name: Driver<String>
let created: Driver<String>
let checked: Driver<String>
}
struct Actions {
let addObservation: (Observable<Patient>) -> Action<String, Void>
}
// MARK:- Public interface
let input: Input
let output: Output
lazy var action = Actions(addObservation: self.addObservation)
// MARK:- Private properties
private let dependencies: Dependencies
private let patientSubject = ReplaySubject<Patient>.create(bufferSize: 1)
private let patient: BehaviorRelay<Patient>
private let disposeBag = DisposeBag()
// MARK:- Initialiser
init(dependencies: Dependencies) {
self.dependencies = dependencies
let patientName = patientSubject
.flatMap { patient in // have to flatMap otherwise you get Observable<Observable<String>>!
return patient.rx.observe(String.self, "name")
}
.flatMap { $0 == nil ? Observable.empty() : Observable.just($0!) }
.asDriver(onErrorJustReturn: "ERROR")
let patientCreated = patientSubject
.flatMap { patient in
return patient.rx.observe(Date.self, "created")
}
.map { Utilities.createFormattedStringFrom(date: $0)}
.asDriver(onErrorJustReturn: "ERROR")
let patientChecked = patientSubject
.flatMap { patient in
return patient.rx.observe(Date.self, "checked")
}
.map { Utilities.createFormattedStringFrom(date: $0)}
.asDriver(onErrorJustReturn: "ERROR")
self.input = Input() // No inputs from viewController in this instance
self.output = Output(name: patientName, created: patientCreated, checked: patientChecked)
}
// MARK:- Actions
private lazy var addObservation: (Observable<Patient>) -> Action<String, Void> = { [unowned self] patient in
return Action { text in
patient.subscribe(onNext: { patient in
return self.dependencies.patientService.addObservation(patient: patient, text: text).map { _ in }
}
.disposed(by: self.disposeBag)
)}(self.patient.asObservable())
}
}
// View controller binding method
func bindViewModel() {
viewModel.output.name
.drive(nameLabel.rx.text)
.disposed(by: disposeBag)
viewModel.output.created
.drive(createdLabel.rx.text)
.disposed(by: disposeBag)
viewModel.output.checked
.drive(checkedLabel.rx.text)
.disposed(by: disposeBag)
addObservationButton.rx.tap
.withLatestFrom(observationTextField.rx.text.orEmpty)
.subscribe(viewModel.action.addObservation.inputs)
.disposed(by: disposeBag)
}