我有一个与此类似的代码结构:
if !checkFirstName(firstName: firstNameField.text!) {
firstNameField.text = "foo"
return false
}
firstNameField.text = "bar"
if !checkLastName(lastName: lastNameField.text!) {
lastNameField.text = "foo"
return false
}
lastNameField.text = "bar"
...
这里的问题是我必须再做几次检查,但它们的区别仅在于函数名称和我正在处理的UITextField
。
我确实希望它们成为单个for
循环或map
的一部分,但似乎我无法使用Selector()
使其工作,有点类似于以下:
let functionNames = ["FirstName", "LastName", ...]
let fields = ["FirstName": firstNameField, "LastName": lastNameField, ...]
...
for name in functionNames {
let sel = Selector("check" + name + ":")
if !view.perform(sel) {
fields[name].text = "foo"
return false
}
fields[name].text = "bar"
return true
}
在Swift中不建议使用 Selector()
,即使它可能有效,我也要避免使用它。
我是否应该进一步研究使Selector()
工作还是整个复制问题是一个架构问题?在任何情况下,我怎么能避免它
答案 0 :(得分:1)
我建议从您的视图中获取所有文本字段,然后继续使用泛型函数。
(我没有编译下面的代码。)
func getAllTextFields() -> [UITextField] {
var results:[UITextField] = []
for subview in view.subviews {
results += getAllTextFields(in: subview)
if subview.isKind(of: UITextField.self) {
if let textField = subview as? UITextField {
results.append(textField)
}
}
}
return results
}
func YourFuncName() -> Bool {
var allTextFields = getAllTextFields()
var returnValue = true
for textField in allTextFields {
if !checkTextField(text: textField.text) {
textField.text = “foo”
returnValue = false
break
} else {
textField.text = “bar”
}
}
return returnValue
}
func checkTextField (text :String ) -> Bool {
//Your checking func body goes here
}
修改:我可以执行“执行选择器”
答案 1 :(得分:1)
函数是Swift中的第一类对象,这意味着你也可以像变量一样传递它们。不是动态地构建函数名,而是将它们与元组中的UITextField
相关联。
假设你有这些功能:
func check (firstName: String) -> Bool {
// ...
}
func check (lastName: String) -> Bool {
// ....
}
你可以像这样循环它们:
// checks is an array of tuples. Each tuple has 2 components:
// a UITextField and a function which takes a String and return a Bool
let checks: [(field: UITextField, checker: (String) -> Bool)] = [
(firstNameField, check(firstName:)),
(lastNameField , check(lastName:))
]
for c in checks {
guard c.checker(c.field.text!) else {
c.field.text = "foo"
return false
}
c.field.text = "bar"
}