あなたの問題は、拡張機能を介してプロトコル準拠を追加できますが、拡張機能はそのクラスのインスタンスではなく、クラスに適用されることです。これは、次のように言うことができることを意味します。
extension UITextField: ValidatesName {...}
しかし、これにより UITextField のすべてのインスタンスが準拠しますValidatesName
同様に、次のようにも言えます。
extension UITextField: ValidatesEmail{...}
しかし、今では UITextField のすべてのインスタンスがValidatesName および 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")
}
}