MagneticFields 是一个用于向您的模型对象添加字段的库。它将为您提供
MagneticFields 通过 CocoaPods 提供。要安装它,请将以下行添加到您的 Podfile
pod "MagneticFields"
要运行示例项目,请先从仓库克隆,然后从 Example 目录中的项目运行 pod install
class Person {
let age = Field<Int>()
}
person.age.value = 10
基本字段类型是 Field
,一个参数化类,其类型参数是其值类型。对于多值字段,有 ArrayField
,它封装了描述单值类型的另一个字段。
let tag = Field<String>(name: "Tag")
let tags = ArrayField(Field<String>(), name: "Tag")
内部字段负责验证、转换等。`ArrayField` 拥有顶级属性,如 `name`、`key` 等。 – 但为了方便,它在初始化时将从内部字段复制。
提供一个一元前缀操作符 *
来在 ArrayField
中包装一个 Field
。因此,您也可以像这样编写上述声明
let tags = *Field<String>(name: "Tag")
简单的闭包验证
let age = Field<Int>().require { $0 > 0 }
规则也可以链接起来,这意味着 AND。顺序不重要。
let age = Field<Int>().require { $0 > 0 }.require { $0 % 2 == 0 }
默认情况下,`nil` 值将被认为是有效的。要为给定规则更改这一点,将 `allowNil: false` 传递给 `require`。
要验证字段值,可以调用 `field.valid`(返回 `Bool`)或调用 `field.validate()`,它返回 `ValidationState` 枚举
public enum ValidationState:Equatable {
case Unknown
case Invalid([String])
case Valid
}
.Invalid
案例的关联值是一个错误消息列表(例如,`["必须大于 0", "是必需的"]`)。
字段将自动具有以下时间戳
updatedAt
:任何值被设置的最后一个时间changedAt
:设置新值的时间(使用==
进行比较)此库包含用于通用、类型安全变更观察的Observer
和Observable
协议。字段同时实现这两个协议。
Observable
可以有不同的注册Observer
对象。箭头操作符是addObserver
方法(<--
作用相同,只是参数顺序相反)的快捷方式。在添加观察者后,触发观察事件一次,之后每当字段值被设置时也触发。
如果观察者实现了Observer
协议,它包含一个valueChanged(observable, value: value)
方法,则可以添加观察者。
field --> observer
或者,可以提供闭包。使用owner
代替观察者对象,仅用于识别每个闭包;每个所有者只能有一个相关的闭包。
field --> owner { value in
print(value)
}
即使没有给出观察者,也可以注册闭包。这实际上是在注册一个空观察者的闭包。一次只能有一个这样的闭包。
age --> { value in
print("Age was changed to \(value)")
}
由于Field
本身实现了Observable
和Observer
,可以使用箭头操作符创建两个字段值之间的链接。
sourceField --> destinationField
这将在立即设置destinationField
的值与sourceField
相同,并且每当sourceField
的值改变时再次设置。
<-->
操作符是先调用<--;
再调用-->
的快捷方式(只能在两个字段之间使用)。
field1 <--> field2
由于先调用<--;
,两个字段将最初具有field2
的值。
字段和Observables具有强类型value
属性,它必须与观察者关联的类型(ValueType
)或闭包的参数匹配。
因此,这会导致编译失败
let name = Field<String>()
let age = Field<Int>()
name --> age
注销观察者使用的是removeObserver
方法或-/->
操作符。使用removeAllObservers()
可以移除所有观察者。
区分一个值因为尚未加载(例如,从API加载)而为空,以及一个已知为空值的值可能很有用。为此,字段提供了返回LoadState
枚举值的state
属性。
public enum LoadState {
case NotSet
case Set
case Loading
case Error
}
所有字段最初都在.NotSet
状态,但一旦它们的值被设置为任何东西,就自动变为.Set
。
当加载过程需要花费一定时间时,可以使用.Loading
状态。例如,在发出API请求时,你可能在UI中显示一个旋转器。