基于可观察的动作创建动作

时间:2019-04-14 17:14:37

标签: swift action rx-swift

我正在基于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)
    }

0 个答案:

没有答案