【问题标题】:Rxswift ios - Validate OTP field and Confirm OTP field on button clickRxswift ios - 验证 OTP 字段并在按钮单击时确认 OTP 字段
【发布时间】:2021-01-18 14:06:45
【问题描述】:

我是 RxSwift 的新手,想在我的项目中实现一个功能。 我必须在提交点击时使用 RxSwift 使用输入/输出 MVVM 验证 2 个字段 OTP 和 Confirm OTP。

案例1:如果任何文本字段为空,则应禁用提交按钮,因此如果用户开始输入第一个文本字段,则将启用提交按钮(确认 OTP 文本字段也相同)

案例2:在提交点击时,我需要验证任一文本字段是否为空并在屏幕上显示错误,此外,如果两个文本字段的值不匹配,它将在提交按钮点击时显示错误。


let otpChangedText = BehaviorSubject<String>(value:"")
let confirmOtpChangedText = BehaviorSubject<String>(value:"")
let submitButtonTapped = PublishSubject<Void>()

let otp1Validation =  otpChangedText.skipWhile { $0.isEmpty}.map {Validator.isEmpty(string: $0)}

let isValidOtp =  otp1Validation.asDriver(onErrorJustReturn:false)

outputs = Outputs (isValidOTP: isValidOtp)

我以某种方式实现了提交按钮禁用状态,但不知道如果任何字段为空并且两个文本字段的值不匹配,我应该如何在屏幕上显示错误。

请指导我。谢谢

【问题讨论】:

    标签: ios swift mvvm rx-swift


    【解决方案1】:

    顺便说一句,来自书"Intro To Rx"

    主题提供了一种方便的方式来查看 Rx,但不建议将它们用于日常使用。

    你不应该把所有这些主题都混在一起......


    首先让我们创建您的业务规则:

    // Case 1
    func eitherFilled(first: String?, second: String?) -> Bool {
        first != nil && !first!.isEmpty || second != nil && !second!.isEmpty
    }
    
    // Case 2
    func hasError(first: String?, second: String?) -> Bool {
        first == nil || second == nil || first != second
    }
    

    您可以独立于 Rx 或其他任何东西来测试它们,以确保它们是正确的。

    现在创建您的视图模型:

    // Case 1
    func buttonEnabled(first: Observable<String?>, second: Observable<String?>) -> Observable<Bool> {
        Observable.combineLatest(first, second, resultSelector: eitherFilled)
    }
    
    // Case 2
    func displayError(first: Observable<String?>, second: Observable<String?>) -> Observable<Void> {
        Observable.combineLatest(first, second, resultSelector: hasError)
            .filter { $0 }
            .map { _ in }
    }
    

    同样,这些都非常容易使用 RxTest 进行测试。

    现在您可以将视图模型安装到视图控制器中,并且您知道它们可以工作,因为您已经对其进行了测试。 (注意:我没有测试过它们。我把它留给你来确保逻辑是正确的。)

    final class MyViewController: UIViewController {
        @IBOutlet weak var otpField: UITextField!
        @IBOutlet weak var confirmOtpField: UITextField!
        @IBOutlet weak var button: UIButton!
        let disposeBag = DisposeBag()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Case 1
            buttonEnabled(
                first: otpField.rx.text.asObservable(),
                second: confirmOtpField.rx.text.asObservable()
            )
            .bind(to: button.rx.isEnabled)
            .disposed(by: disposeBag)
    
            // Case 2
            displayError(
                first: otpField.rx.text.asObservable(),
                second: confirmOtpField.rx.text.asObservable()
            )
            .bind {
                finalPresentScene(animated: true) {
                    UIAlertController(title: "Error", message: "OTP fileds do not match.", preferredStyle: .alert).scene { $0.connectOK() }
                }
            }
            .disposed(by: disposeBag)
        }
    }
    

    因此,有了以上所有内容,您有两个模型代表您的业务规则,两个视图模型将这些业务规则转换为视图更新,您的视图控制器用于将视图模型连接到视图。

    (如果您想了解更多关于我用来呈现警报的代码,请参阅此 GitHub 存储库:https://github.com/danielt1263/CLE-Architecture-Tools

    【讨论】:

    • T.感谢您的帮助。 ``` buttonEnabled(第一个:otpField.rx.text.asObservable(),第二个:confirmOtpField.rx.text.asObservable()) .bind(to: button.rx.isEnabled) .disposed(by: disposeBag) ```如果任何字段有值,此代码可以正常工作,但我的要求是如果 OTP 字段中有文本然后启用按钮,现在如果用户移动到确认 OTP 字段并且到目前为止没有值然后禁用按钮.所以我必须检查活动字段是否为空然后禁用按钮&如果活动字段有值然后启用
    • 这与您在问题中描述的要求不同,但原理是相同的。概述哪些用户事件导致按钮的启用状态发生更改。定义逻辑,制作视图模型,然后将其连接到视图控制器中。
    • 我正在尝试从昨天开始解决这个问题,但仍然无法解决。那么我是否必须捕获文本字段事件?像 textfieldShouldBeginEditing 来检查哪个文本字段当前处于活动状态?你能帮我解决这个问题吗?我真的很感谢你的帮助。谢谢
    • 提出这个新问题,我会尝试回答。请详细说明您的要求,因为您在评论中所说的对我来说没有多大意义。
    • 再次感谢您的帮助。我发布了一个新问题link
    猜你喜欢
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 2021-05-23
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多