Rx Swift: проверка сложных текстовых полей
Я новичок в RxSwift
и все примеры, которые я нашел, относятся к простым случаям.
Я пытаюсь сделать проверку формы для моих текстовых полей. Мой пользовательский класс TextField имеет метод isValid()
и regexp
, isValid
возврат основан на regexp
приписывать.
До сих пор я написал следующее:
let valids = [mLastName, mFirstName, mEmailField].map {
$0.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, { $0 && $1 })
}.subscribe(onNext: { allValid in
///update button according to AllValid
})
Кто-нибудь знает, как обновить код для базы первым Observable<Bool>
основываться на моем isValid()
метод вместо text!.characters.count
2 ответа
Я нашел ответ сам. Проблема была в первой карте, я не должен использовать анонимный параметр.
Увидеть:
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 $0 && $1 })
}.bindTo(self.mValidateButton.rx.isEnabled)
Вероятно, есть много способов сделать это.
Ты можешь использовать filter
преобразовывать rx.text
Наблюдаемый в вашем пользовательском классе TextField:
var isTextValid: Observable<Bool> {
return rx.text.filter { _ in
return self.isValid()
}
}
тогда вы можете объединить isTextValid
из всех текстовых полей с combineLatest
,
Вы также можете извлечь логику проверки из настраиваемого текстового поля (возможно, вам даже не нужно настраиваемое текстовое поле вообще).
Выгоды:
- проверка может быть проще для модульного теста
- вы можете легко повторно использовать проверку в разных местах вашего приложения (например, для
UITextView
если ты когда-нибудь им воспользуешься).
Проект класса валидатора:
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()
делает.