2015-02-17 3 views
2

Я пытаюсь создать простую структуру обработки ошибок в Swift. То, что я хотел бы сделать, это вернуть тип, который включает либо код «Успех», либо код «Ошибка». Но чтобы сделать это немного сложным, в случае ошибки, я также хочу получить сообщение и диагностическую строку.Как вернуть Swift enum для обработки ошибок

Я придумал это, который отлично компилируется и работает просто замечательно, насколько возвращение успеха/ошибки:

enum PasswordValidationResult { 
    case Success 
    case PasswordError(message: String, diagnostic: String) 

    func isValid() -> Bool { 
     switch self { 
     case .Success: 
      return true 
     case .PasswordError: 
      return false 
     } 
    } 
} 

И я могу вернуть нужное значение (ы):

return PasswordValidationResult.PasswordError(message: "You can't do that", diagnostic: "XYZ") 

Проблема возникает, когда я пытаюсь ссылаться на возвращаемое значение.

Очевидно, я могу использовать функцию isValid(), чтобы проверить условие успеха, но я не могу найти синтаксис для ссылки на сообщение и диагностические строки.

Например, пытаясь это:

myError = someFunction() 

    if myError == PasswordValidationResult.Error { 
    // None of this will compile, at all... 
    println(myError.message) 
    } 

ответ

6

Вы можете извлечь связанные значения перечисления с использованием switch:

switch someFunction() { 
case .Success: 
    println("It worked!") 
case .PasswordError(let message, let diag): 
    println(message) 
} 

Среди других приятных вещей switch делает, если ваши случаи исчерпывают все возможности (как здесь - перечисление должно быть одним из двух значений), вам не нужно значение по умолчанию. И если вы забудете и пропустите один, компилятор предупредит вас.

Обратите внимание, вы можете также соответствовать определенные значения:

switch someFunction() { 
case .Success: 
    println("It worked!") 
case .PasswordError("Password invalid", _): 
    println("Please try again") 
case let .PasswordError(message, diag): 
    // more general error handling 
} 
+0

Таким образом, давая те части 'PasswordError' имен кортежей в объявлении не имеет смысла. – nhgrif

+0

@nhgrif не уверен, что вы имеете в виду –

+0

'case PasswordError (сообщение: String, diagnostic: String)' <- из фрагмента кода в вопросе. Именование частей этого кортежа бессмысленно, не так ли? – nhgrif

2

Другой, чуть более удобный способ доступа этих значений является добавление вычисляемых свойства к enum для каждого связанного значения:

enum PasswordValidationResult { 
    // ... 

    var errorMessage: String? { 
     switch self { 
     case let .PasswordError(message, _): 
      return message 
     default: 
      return nil 
     } 
    } 

    var errorDiagnostic: String? { 
     switch self { 
     case let .PasswordError(_, diagnostic): 
      return diagnostic 
     default: 
      return nil 
     } 
    } 
} 

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

+0

Спасибо Нейту, хороший совет. – Zac

1

Вы можете извлечь соответствующее значение, как кортеж с именами элементов с использованием switch:

let myError = someFunction() 

switch myError { 
case .Success: 
    println("success") 
case .PasswordError(let err): 
    println("message: \(err.message)") 
    println("diagnostic: \(err.diagnostic)") 
} 
+0

Также хороший совет ... не знал, что вы можете захватить весь кортеж таким образом. – Zac

Смежные вопросы