问题
I have to implement below scenarios with RxSwift MVVM
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:
- If OTP field has value then enable the button or disable it if no value
- User taps on the Confirm OTP field, it is empty now so disable the button again
- If user deletes the value from OTP field, disable the button again (As it is empty, same with Confirm OTP field)
Thanks
回答1:
Updated answer:
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)
Old answer:
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(""))
来源:https://stackoverflow.com/questions/65810539/rxswift-enable-disable-button-based-on-textfield-input