基于文本框输入的 RxSwift 启用/禁用按钮 [英] RxSwift enable/disable button based on textfield input

查看:65
本文介绍了基于文本框输入的 RxSwift 启用/禁用按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须使用 RxSwift MVVM 实现以下场景

I have to implement below scenarios with RxSwift MVVM

我有两个文本字段(OTP 和确认 OTP)和一个提交按钮,如果用户在 OTP 文本字段上没有值时单击 OTP 文本字段,则应禁用提交按钮,现在如果用户在 otp 文本字段中键入内容按钮应启用.现在,如果用户点击第二个文本字段,因为它现在是空白的,那么应该再次禁用该按钮它只有在有值时才启用.

I have two textfields (OTP & Confirm OTP) and a Submit button, If user clicks on the OTP textfield when there is no value on the OTP textfield then submit button should be disabled, Now if user types something in otp textfield button should be enabled. Now if user taps on the second text field as it is blank now then the button should be disabled again & its get enabled only when there is a value.

所以基本上我想通过检查启用/禁用按钮:

So basically I want to enable/disable the button by checking:

  1. 如果 OTP 字段有值,则启用按钮,如果没有值则禁用它
  2. 用户点击确认 OTP 字段,它现在是空的,所以再次禁用按钮
  3. 如果用户从 OTP 字段中删除该值,则再次禁用该按钮(因为它是空的,与确认 OTP 字段相同)

谢谢

推荐答案

更新答案:

正如@Daniel T. 指出的,这可以在不使用主题的情况下解决:

As @Daniel T. noted, this can be solved without using the Subject:

let disposeBag = DisposeBag()

let otpFieldIsFocused = Observable.merge(
    otpField.rx.controlEvent(.editingDidBegin).map { true },
    otpField.rx.controlEvent(.editingDidEnd).map { false }
)

// Sends only when the field is first responder
let otpFieldIsNotEmpty = otpField.rx.text.orEmpty
    .map { $0.isEmpty }
    .withLatestFrom(otpFieldIsFocused) {
        (isEmpty: $0, isFocused: $1)
    }
    .filter { $0.isFocused }
    .map { !$0.isEmpty }

let otpConfirmFieldIsFocused = Observable<Bool>.merge(
    otpConfirmField.rx.controlEvent(.editingDidBegin).map { true },
    otpConfirmField.rx.controlEvent(.editingDidEnd).map { false }
)

let otpConfirmFieldIsNotEmpty = otpConfirmField.rx.text.orEmpty
    .map { $0.isEmpty }
    .withLatestFrom(otpConfirmFieldIsFocused) {
        (isEmpty: $0, isFocused: $1)
    }
    .filter { $0.isFocused }
    .map { !$0.isEmpty }

Observable.merge(otpFieldIsNotEmpty, otpConfirmFieldIsNotEmpty)
    .startWith(false)
    .bind(to: button.rx.isEnabled)
    .disposed(by: disposeBag)

旧答案:

这可以使用 switchLatest 语句来完成:

This can be done using the switchLatest statement:

import RxSwift
import RxCocoa

...

let disposeBag = DisposeBag()
let subject = PublishSubject<Observable<String>>()

otpField.rx
    .controlEvent(.editingDidBegin)
    .subscribe(onNext: {
        subject.onNext(otpField.rx.text.orEmpty.asObservable())
    })
    .disposed(by: disposeBag)

otpConfirmField.rx
    .controlEvent(.editingDidBegin)
    .subscribe(onNext: {
        subject.onNext(otpConfirmField.rx.text.orEmpty.asObservable())
    })
    .disposed(by: disposeBag)

subject
    .switchLatest()
    .map { !$0.isEmpty }
    .startWith(false)
    .distinctUntilChanged()
    .bind(to: button.rx.isEnabled)
    .disposed(by: disposeBag)

otpField.becomeFirstResponder()

如果你需要禁用按钮,例如当两个字段都失去焦点时,那么你可以这样做:

If you need to disable the button, for example, when both fields lose focus, then you can do it like this:

subject.onNext(.just(""))

这篇关于基于文本框输入的 RxSwift 启用/禁用按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆