您的问题是,虽然您可以通过扩展添加协议一致性,但扩展应用于类,而不是该类的实例。这意味着您可以这样说:
extension UITextField: ValidatesName {...}
但这将使UITextField 的所有实例都符合ValidatesName
同样,你也可以说
extension UITextField: ValidatesEmail{...}
但是现在UITextField 的所有实例都将符合ValidatesName
and ValidatesEmail
。
无论如何,拥有单独Validates...
的协议似乎不是正确的方法。你的协议的基本签名是这样的var isValid: Bool
;这不会在名称和电子邮件之间改变。改变的是验证逻辑,它必须存在于某个地方。再加上您需要子类才能使用 Interface Builder,这表明Validatable
您的各种子类可以采用的单一协议是一种更合理的方法。
protocol Validatable {
var isValid: Bool { get }
}
现在,您可以定义符合此协议的 UITextField 的子类(如果您愿意,可以通过对子类的扩展添加符合性,我只是想在这里节省空间)
class NameTextField: UITextField, Validatable {
var isValid: Bool {
get {
guard let text = self.text else {
return false
}
return !text.isEmpty
}
}
}
class EmailTextField: UITextField, Validatable {
var isValid: Bool {
get {
guard let text = self.text else {
return false
}
return text.contains("@")
}
}
}
现在,您可以将文本字段添加到数组中,并具有以下内容:
@IBOutlet weak var nameTextField:NameTextField!
@IBOutlet weak var emailTextField:EmailTextField!
var validatableFields:[Validatable]!
override func viewDidLoad() {
super.viewDidLoad()
self.validatableFields = [nameTextField,emailTextField]
}
...
for field in validateableFields {
if !field.isValid() {
print("A field isn't valid")
}
}