Сделайте перечисление с двумя случаями, конвертируемыми в Bool в Swift - PullRequest
0 голосов
/ 08 октября 2018

У меня есть перечисление, которое я использую для проверки текста, определенное следующим образом:

enum Validity {
    case valid
    case invalid(reason: String)
}

My TextValidator имеет функцию, которая проверяет ввод текста и возвращает Validity:

func validate(_ string: String) -> Validity

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

Однако во многих случаях мне просто нужна логическая проверка, если строка действительна- например, для включения / выключения кнопки отправки.Код, который я сейчас использую для этого:

let validity = validator.validate("user input string")
submitButton.isEnabled = (validity == .valid)

, что плохо читается, и поэтому я бы предпочел написать что-то вроде:

let isValid: Bool = validator.validate("user input string")
submitButton.isEnabled = isValid

иликороче:

submitButton.isEnabled = validator.validate("user input string")

В качестве "быстрого исправления" я определил вычисленное логическое свойство isValid для моего перечисления Validity, чтобы я мог по крайней мере написать:

submitButton.isEnabled = validator.validate("user input string").isValid

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

Итак, мой вопрос:

Есть ли способ сделать перечисление неявно конвертируемым в Bool в Swift?

Или, если нет: Можете ли вы вспомнитьдругой подход, который сохраняет преимущества обоих типов - Bool и enum?

1 Ответ

0 голосов
/ 08 октября 2018

Вы можете добиться этого, перегрузив функцию validate, чтобы также вернуть Bool.

enum Validity {
    case valid
    case invalid(reason: String)
}

// Example validate function
func validate(_ string: String) -> Validity {
    if string.count < 5 {
         return .valid
    } else {
        return .invalid(reason: "String too long")
    }
}

// Overloaded function which returns Bool
func validate(_ string: String) -> Bool {
    let validity: Validity = validate(string)
    if case .valid = validity {
        return true
    } else {
        return false
    }
}

// Swift expects the result of validate to be a Bool, so it calls the
// (String) -> Bool version of validate
let b1: Bool = validate("this")
print(b1)
true
// Here, the result of validate is used in an if, so Swift is expecting
// a Bool result and calls the (String) -> Bool version of validate
if validate("this is a test") {
    print("the string is valid")
} else {
    print("the string is invalid")
}
the string is invalid
let v: Validity = validate("what about this one?")
switch v {
case .valid:
    print("valid")
case .invalid(let reason):
    print("invalid: \(reason)")
}
invalid: String too long
...