Rx Swift:复杂文本字段验证
Rx Swift : Complex TextFields Validation
我是 RxSwift
的新手,我找到的所有示例都是处理简单的案例。
我正在尝试对我的文本字段进行表单验证。
我的自定义 TextField class 有一个方法 isValid()
和一个 regexp
。 isValid
return 基于 regexp
属性。
到目前为止,我已经写了以下内容:
let valids = [mLastName, mFirstName, mEmailField].map {
[=11=].rx.text.map {
text -> Bool in
// I want more complex logic here
// Like return field.isValid()
return text!.characters.count > 0
}
}
let _ = Observable.combineLatest(valids) { iterator -> Bool in
return iterator.reduce(true, { [=11=] && })
}.subscribe(onNext: { allValid in
///update button according to AllValid
})
有谁知道如何更新代码以第一个 Observable<Bool>
基于我的 isValid()
方法而不是 text!.characters.count
我自己找到了答案。问题出在第一张地图上,我不应该使用匿名参数。
参见:
let valids = [mLastName, mFirstName, mEmailField].map { field in
field.rx.text.map({ _ in return field.isValid() })
}
_ = Observable.combineLatest(valids) { iterator -> Bool in
return iterator.reduce(true, { return [=10=] && })
}.bindTo(self.mValidateButton.rx.isEnabled)
可能有很多方法可以做到这一点。
您可以使用 filter
在您的自定义 TextField 中转换 rx.text
Observable class:
var isTextValid: Observable<Bool> {
return rx.text.filter { _ in
return self.isValid()
}
}
然后您可以将所有文本字段中的 isTextValid
与 combineLatest
合并。
您还可以从自定义文本字段中提取验证逻辑(也许您根本不需要自定义文本字段)。
好处:
- 验证可以更容易进行单元测试
- 您可以轻松地在应用的不同位置重复使用验证(例如
UITextView
如果您曾经使用过)。
一个验证者的草案class:
class TextValidator {
var input: Observable<String>
var regex: NSRegularExpression
init(input: Observable<String>, regex: NSRegularExpression) {
self.input = input
self.regex = regex
}
func validate() -> Observable<Bool> {
return input.map { text in
//return true if regex matches the text
}
}
}
然后就可以这样使用了:
let mailValidator = TextValidator(input: mLastName.rx.text, regex: /* actual regex*/)
let firstNameValidator = TextValidator(input: mFirstName.rx.text, regex: ...)
let _ = Observable.combineLatest(mailValidator.validate(), firstName.validate(), ...)
// and so on
现在如果你想为验证器编写单元测试(你可能应该这样做),你可以简单地将 Observable.just("Some value")
作为 input
传递给 TextValidator
并验证 Observable 返回的内容通过 validate()
确实如此。
我是 RxSwift
的新手,我找到的所有示例都是处理简单的案例。
我正在尝试对我的文本字段进行表单验证。
我的自定义 TextField class 有一个方法 isValid()
和一个 regexp
。 isValid
return 基于 regexp
属性。
到目前为止,我已经写了以下内容:
let valids = [mLastName, mFirstName, mEmailField].map {
[=11=].rx.text.map {
text -> Bool in
// I want more complex logic here
// Like return field.isValid()
return text!.characters.count > 0
}
}
let _ = Observable.combineLatest(valids) { iterator -> Bool in
return iterator.reduce(true, { [=11=] && })
}.subscribe(onNext: { allValid in
///update button according to AllValid
})
有谁知道如何更新代码以第一个 Observable<Bool>
基于我的 isValid()
方法而不是 text!.characters.count
我自己找到了答案。问题出在第一张地图上,我不应该使用匿名参数。
参见:
let valids = [mLastName, mFirstName, mEmailField].map { field in
field.rx.text.map({ _ in return field.isValid() })
}
_ = Observable.combineLatest(valids) { iterator -> Bool in
return iterator.reduce(true, { return [=10=] && })
}.bindTo(self.mValidateButton.rx.isEnabled)
可能有很多方法可以做到这一点。
您可以使用 filter
在您的自定义 TextField 中转换 rx.text
Observable class:
var isTextValid: Observable<Bool> {
return rx.text.filter { _ in
return self.isValid()
}
}
然后您可以将所有文本字段中的 isTextValid
与 combineLatest
合并。
您还可以从自定义文本字段中提取验证逻辑(也许您根本不需要自定义文本字段)。
好处:
- 验证可以更容易进行单元测试
- 您可以轻松地在应用的不同位置重复使用验证(例如
UITextView
如果您曾经使用过)。
一个验证者的草案class:
class TextValidator {
var input: Observable<String>
var regex: NSRegularExpression
init(input: Observable<String>, regex: NSRegularExpression) {
self.input = input
self.regex = regex
}
func validate() -> Observable<Bool> {
return input.map { text in
//return true if regex matches the text
}
}
}
然后就可以这样使用了:
let mailValidator = TextValidator(input: mLastName.rx.text, regex: /* actual regex*/)
let firstNameValidator = TextValidator(input: mFirstName.rx.text, regex: ...)
let _ = Observable.combineLatest(mailValidator.validate(), firstName.validate(), ...)
// and so on
现在如果你想为验证器编写单元测试(你可能应该这样做),你可以简单地将 Observable.just("Some value")
作为 input
传递给 TextValidator
并验证 Observable 返回的内容通过 validate()
确实如此。