RxSwift - 按下按钮时显示/隐藏警告标签

时间:2017-04-24 16:53:04

标签: ios swift mvvm reactive-cocoa rx-swift

我使用MVVM模式并尝试仅在用户按下登录按钮时显示警告标签。现在他们不会出现,因为我不知道如何只在用户操作上显示它们。然后,当用户开始编辑时,应隐藏相应标签的警告。 这是我的ViewController,它处理对viewModel的引用:

<div id="content">
This is a test 1<br /><br />
This is a test 2<br /><br />
This is a test 3<br /><br />
This is a test 4<br /><br />
</div>

和ViewModel:

import UIKit
import RxSwift
import RxCocoa
class RxLoginViewController: UIViewController {

    @IBOutlet weak var signInButton: UIButton!
    @IBOutlet weak var phoneNumberTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    @IBOutlet weak var phoneWarningLabel: UILabel!
    @IBOutlet weak var passwordWarningLabel: UILabel!

    fileprivate var viewModel: RxLoginViewModel?
    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        viewModel = RxLoginViewModel(phoneNumber: phoneNumberTextField.rx.text.orEmpty.asDriver(), passwordText: passwordTextField.rx.text.orEmpty.asDriver())
        addBindsToViewModel(viewModel: viewModel!)
        setupButtons()
    }

    fileprivate func addBindsToViewModel(viewModel: RxLoginViewModel) {
        phoneNumberTextField.rx.text
            .orEmpty
            .asObservable()
            .debug("phoneNumberTextField")
            .bindTo(viewModel.phoneNumberText)
            .addDisposableTo(disposeBag)

        passwordTextField.rx.text
            .orEmpty
            .asObservable()
            .debug("passwordTextField")
            .bindTo(viewModel.passwordText)
            .addDisposableTo(disposeBag)

        viewModel.showPhoneWarning
            .asDriver()
            .debug("showPhoneWarning")
            .drive(onNext: { [weak self] showWarning in
                UIView.animate(withDuration: 0.2) {
                    self?.phoneWarningLabel.isHidden = !showWarning
                }}
            )
            .addDisposableTo(disposeBag)

        viewModel.showPasswordWarning
            .asDriver()
            .debug("showPasswordWarning")
            .drive(onNext: { [weak self] showWarning in
                UIView.animate(withDuration: 0.2) {
                    self?.passwordWarningLabel.isHidden = !showWarning
                }
            })
            .addDisposableTo(disposeBag)

        viewModel.credentialsValid
            .debug("credentialsValid")
            .drive(onNext: { [weak self] valid in
                self?.signInButton.isEnabled = valid
                self?.signInButton.alpha = valid ? 1 : 0.5
            })
            .addDisposableTo(disposeBag)
    }

    private func setupButtons() {

        signInButton.rx.tap
            .bindTo(viewModel!.signInAction)
            .addDisposableTo(disposeBag)
    }
}

如何显示任何无效文本字段的警告以及如何过滤ViewModel中的有效字段?

1 个答案:

答案 0 :(得分:3)

我不像你那样做我的视图模型,但希望这会帮助你...

这里的关键是概述可能影响showPhoneWarning可观察的所有内容。

例如,如果在signInAction无效时phoneNumberText进来,您希望observable发出true。

让我们将其表达为变量:

let invalidPhoneNumberOnTap = source.phoneNumberText
    .map { $0.isValidPhoneNumber == false }
    .sample(source.signInAction)

如果phoneNumberText触发新元素,您还希望observable发出false。

let hideWarning = source.phoneNumberText.map { _ in false }

现在你所要做的就是将这两者合并在一起。您还要确保它以false开头,因此警告不会过早显示。

showPhoneWarning = Observable.of(invalidPhoneNumberOnTap, hideWarning)
    .merge()
    .startWith(false)

以同样的方式处理showEmailWarning。