Избегайте множественных предложений if для вызова разных методов

У меня есть подобная структура кода для этого:

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
}

Selector() не рекомендуется в Swift и, даже если это может сработать, я хочу избежать этого.

Должен ли я продолжать исследования в создании Selector() работа или это вся проблема дублирования архитектурная проблема? В любом случае, как мне этого избежать

2 ответа

Решение

Функции являются первоклассными объектами в 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"
}

Я бы предложил получить все текстовые поля из вашего представления, а затем продолжить с общей функцией.

(Я не скомпилировал ниже код.)

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
}

Модифицировано: я могу выполнить "выполнить селектор"

Другие вопросы по тегам