带有内置声明式验证的通用值包装器。
每个应用程序都有数据模型。数据模型通常实现为自定义结构化的数据类型,用于存储一个或多个属性。理想情况下,每个属性的类型(无论是原始类型还是结构化类型)都定义了该属性所有可能值的期望集合。此外,可能存在特殊规则,用于定义任何给定值对于该属性是否可接受。
Swift 没有内置机制来缩小标准数据类型中允许值的集合,也无法评估针对每个给定值的任何特殊规则,以检查它对于该属性是否可接受。
例如,要将一个值限制为 1 到 100 范围内的整数,并避免该范围内的所有奇数,我们通常只使用 Integer,然后在实际将值放入此属性之前,以某种方式实现所需的检查。 这导致业务逻辑的单个部分(对此特定属性的要求)分布在代码库中至少两个(有时更多)位置。
推荐使用 SwiftPM 进行安装,但也支持开箱即用的 Carthage 。
为了描述用户帐户密码的自定义验证规则,让我们定义所谓的 ValueSpecification
。 此规范定义值基本类型(任何预定义的数据类型)以及需要满足的一组要求才能通过验证。
enum Password: ValueSpecification
{
static
let conditions: [Condition<String>] = [
Check("Lenght between 8 and 30 characters"){ 8...30 ~= $0.count },
Check("Has at least 1 capital character"){ 1 <= Pwd.caps.count(in: $0) },
Check("Has at least 4 lower characters"){ 4 <= Pwd.lows.count(in: $0) },
Check("Has at least 1 digit character"){ 1 <= Pwd.digits.count(in: $0) },
Check("Has at least 1 special character"){ 1 <= Pwd.specials.count(in: $0) },
Check("Allowed chars only"){ Pwd.allowed.isSuperset(of: CS(charactersIn: $0)) }
]
}
请注意,Password
被声明为枚举,因为我们只需要它作为范围,它不会被直接实例化——它的名称定义了规范的名称,并且在内部我们指定了必须满足的 conditions
(又名要求)才能通过验证。
在上面的例子中,我们使用像这样定义的简单自定义辅助函数
enum Pwd
{
static
let caps = CS.uppercaseLetters
static
let lows = CS.lowercaseLetters
static
let digits = CS.decimalDigits
static
let specials = CS(charactersIn: " ,.!?@#$%^&*()-_+=")
static
var allowed = caps.union(lows).union(digits).union(specials)
}
请参阅 User.swift 中的 单元测试,以获取最新的综合使用示例。