RxValidator
简单易用、易读、可扩展、灵活的验证检查器。
不使用Rx也能使用。
要求
RxValidator
以Swift 4编写。兼容iOS 8.0+。
安装
CocoaPods
RxValidator通过CocoaPods提供。要安装它,只需将以下行添加到您的Podfile:
pod 'RxValidator'
概览
您只需这样用:
//without Rx
Validate.to(TargetValue)
.validate(condition)
...
.validate(condition)
.asObservable() or .check()
//with Rx
observable
.validate(condition)
...
.validate(condition)
.subscribe(...)
使用方法
字符串
Validate.to("word is not empty")
.validate(StringShouldNotBeEmpty())
.check()
// result -> RxValidatorResult.valid
//multiple condition
Validate.to("[email protected]")
.validate(StringShouldNotBeEmpty())
.validate(StringIsNotOverflowThen(maxLength: 50))
.validate(StringShouldBeMatch("[a-z]+@[a-z]+\\.[a-z]+"))
.check()
// result -> RxValidatorResult.valid
日期
let targetDate: Date //2018-05-05
let sameTargetDate: Date
let afterTargetDate: Date
let beforeTargetDate: Date
Validate.to(Date())
.validate(.shouldEqualTo(date: sameTargetDate)) //(1)
.validate(.shouldAfterOrSameThen(date: sameTargetDate)) //(2)
.validate(.shouldBeforeOrSameThen(date: sameTargetDate)) //(3)
.validate(.shouldBeforeOrSameThen(date: afterTargetDate)) //(4)
.validate(.shouldBeforeThen(date: afterTargetDate)) //(5)
.validate(.shouldAfterOrSameThen(date: beforeTargetDate)) //(6)
.validate(.shouldAfterThen(date: beforeTargetDate)) //(7)
.check()
// check() result
// valid result -> RxValidatorResult.valid
// (1) not valid -> RxValidatorResult.notEqualDate
// (2) not valid -> RxValidatorResult.notAfterDate
// (3) not valid -> RxValidatorResult.notBeforeDate
// (4) not valid -> RxValidatorResult.notBeforeDate
// (5) not valid -> RxValidatorResult.notBeforeDate
// (6) not valid -> RxValidatorResult.notAfterDate
// (7) not valid -> RxValidatorResult.notAfterDate
整型
Validate.to(2)
.validate(NumberShouldBeEven())
.check()
//.valid
Validate.to(1)
.validate(NumberShouldBeEven())
.check()
//.notEvenNumber
与 RxSwift 一起工作
字符串
Validate.to("word is not empty")
.validate(StringShouldNotBeEmpty())
.asObservable()
.subscribe(onNext: { value in
print(value)
//print("word is not empty")
})
.disposed(by: disposeBag)
Validate.to("word is not empty")
.validate(StringShouldNotBeEmpty())
.asObservable()
.map { $0 + "!!" }
.bind(to: anotherObservableBinder)
.disposed(by: disposeBag)
//Multiple condition
Validate.to("[email protected]")
.validate(StringShouldNotBeEmpty()) //(1)
.validate(StringIsNotOverflowThen(maxLength: 50)) //(2)
.validate(StringShouldBeMatch("[a-z]+@[a-z]+\\.[a-z]+")) //(3)
.asObservable()
.subscribe(onNext: { value in
print(value)
//print("[email protected]")
},
onError: { error in
let validError = RxValidatorResult.determine(error: error)
// (1) validError -> RxValidatorResult.stringIsEmpty
// (2) validError -> RxValidatorResult.stringIsOverflow
// (3) validError -> RxValidatorResult.stringIsNotMatch
})
.disposed(by: disposeBag)
整型
Validate.to(2)
.validate(NumberShouldBeEven())
.asObservable()
.subscribe(onNext: { value in
print(value)
//print(2)
})
.disposed(by: disposeBag)
Validate.to(1)
.validate(NumberShouldBeEven())
.asObservable()
.subscribe(onNext: { value in
print(value)
//print(1)
},
onError: { error in
let validError = RxValidatorResult.determine(error: error)
//validError -> RxValidatorResult.notEvenNumber
})
.disposed(by: disposeBag)
日期
let targetDate: Date //2018-05-05
let sameTargetDate: Date
let afterTargetDate: Date
let beforeTargetDate: Date
Validate.to(Date())
.validate(.shouldEqualTo(date: sameTargetDate)) //(1)
.validate(.shouldAfterOrSameThen(date: sameTargetDate)) //(2)
.validate(.shouldBeforeOrSameThen(date: sameTargetDate)) //(3)
.validate(.shouldBeforeOrSameThen(date: afterTargetDate)) //(4)
.validate(.shouldBeforeThen(date: afterTargetDate)) //(5)
.validate(.shouldAfterOrSameThen(date: beforeTargetDate)) //(6)
.validate(.shouldAfterThen(date: beforeTargetDate)) //(7)
.asObservable()
.subscribe(onNext: { value in
print(value) //print("2018-05-05")
}, onError: { error in
let validError = RxValidatorResult.determine(error: error)
// (1) validError -> RxValidatorResult.notEqualDate
// (2) validError -> RxValidatorResult.notAfterDate
// (3) validError -> RxValidatorResult.notBeforeDate
// (4) validError -> RxValidatorResult.notBeforeDate
// (5) validError -> RxValidatorResult.notBeforeDate
// (6) validError -> RxValidatorResult.notAfterDate
// (7) validError -> RxValidatorResult.notAfterDate
})
.disposed(by: disposeBag)
从可观察对象中链式调用
textField.rx.text
.filterNil()
.validate(StringIsAlwaysPass())
.subscribe(onNext: { (text) in
print(text)
})
.disposed(by: disposeBag)
let text = PublishSubject<String>()
text
.validate(StringIsAlwaysPass())
.subscribe(onNext: { (text) in
print(text)
})
.disposed(by: disposeBag)
即时条件验证
Validate.to("swift")
.validate({ $0 == "objc" })
.check()
Validate.to(7)
.validate({ $0 > 10 })
.check()
Validate.to(Date())
.validate({ !$0.isToday })
.check()
Validate.to("swift")
.validate({ $0 == "objc" }, message: "This is not swift")
.check()
Validate.to(7)
.validate({ $0 > 10 }, message: "Number is too small.")
.check()
Validate.to(Date())
.validate({ !$0.isToday }, message: "It is today!!")
.check()
ResultType
enum RxValidatorResult
case notValid
case notValidWithMessage(message: String)
case notValidWithCode(code: Int)
case undefinedError
case stringIsOverflow
case stringIsEmpty
case stringIsNotMatch
case notEvenNumber
case invalidateDateTerm
case notBeforeDate
case notAfterDate
case notEqualDate
http://reactorkit.io)
使用ReactorKit (func mutate(action: Action) -> Observable<Mutation> {
....
case let .changeTitle(title):
return Validate.to(title)
.validate(StringIsNotOverflowThen(maxLength: TITLE_MAX_LENGTH))
.asObservable()
.flatMap { Observable<Mutation>.just(.updateTitle(title: $0)) }
.catchError({ (error) -> Observable<Mutation> in
let validError = ValidationTargetErrorType.determine(error: error)
return Observable<Mutation>.just(.setTitleValidateError(validError, title))
})
....
支持的验证规则
//String
StringShouldNotBeEmpty()
StringIsNotOverflowThen(maxLength: Int)
StringShouldBeMatch("regex string")
//Int
NumberShouldBeEven()
//Date
DateValidatorType.shouldEqualTo(Date)
DateValidatorType.shouldBeforeThen(Date)
DateValidatorType.shouldBeforeOrSameThen(Date)
DateValidatorType.shouldAfterThen(Date)
DateValidatorType.shouldAfterOrSameThen(Date)
DateValidatorType.shouldBeCloseDates(date: Date, termOfDays: Int)
像这样制作自定义 ValidationRule
//String Type
class MyCustomStringValidationRule: StringValidatorType {
func validate(_ value: String) throws {
if {notValidCondition} {
throw RxValidatorResult.notValidate(code: 999) //'code' must be defined your self.
}
}
}
//Int Type
class MyCustomIntValidationRule: IntValidatorType {
func validate(_ value: Int) throws {
if {notValidCondition} {
throw RxValidatorResult.notValidate(code: 999) //'code' must be defined your self.
}
}
}
我想成为...
- 更多内建验证规则。 (帮助我。欢迎参与 Pull Request。)
- 支持更多类型(数组、浮点数、双精度浮点数等)
- 通过泛型实现更多灵活的代码。