Search code examples
iosswifterror-handlingswift-playgrounddo-catch

How to get the correct error when hitting a do catch block for a function that throws when String does not conform to Error?


import Foundation

enum ErrorScenarios: Error {
    case invalidAge
    case invalidEmail
    case incorrectData
}

func age(age:Int) throws {
    if age < 20 {
        throw ErrorScenarios.invalidAge
    }
    print("You have a valid age of \(age)")
}

extension ErrorScenarios: LocalizedError {
    var localizedDescription: String {
        switch self {
        case .incorrectData:
            return "Incorrect data provided"
        case .invalidAge:
            return "Incorrect age was provided"
        case .invalidEmail:
            return "Incorrect email provided"
        }
    }
}

Here I'm using a do catch block to catch the invalidAge error scenario, I'm not quite sure if this is correct? When I run the playground the catch block never gets hit.

do {
    try age(age: -23)
}
catch {
    throw ErrorScenarios.invalidAge
}

Here as an alternative to the do catch block I deal with the error by making it an optional therefore I'm guessing a do catch block is not required. However when printing the result it returns Optional(() rather than an optional Int. Any help would be appreciated where I'm going wrong.

let result = try? age(age: 34)
print(result)

Solution

  • The problem is that you are throwing another error instead of consuming the one that's being thrown by your age method:

    do {
        try age(age: -23)
    } catch {
        if let error = error as? ErrorScenarios {
            print("ErrorScenarios:", error)  // "ErrorScenarios: Incorrect age was provided\n"
            switch error {
            case .incorrectData:
                print("invalidAge")
                 case .invalidAge:
                print("invalidAge")   // "invalidAge\n"
                 case .invalidEmail:
                print("invalidEmail")
            }
        } else {
            print("Error:", error)
        }
    }
    

    Or if you prefer multiple catch blocks:

    do {
        try age(age: -23)
    } catch let error as ErrorScenarios {
        print("ErrorScenarios:", error)
        switch error {
        case .incorrectData:
            print("invalidAge")
        case .invalidAge:
            print("invalidAge")
        case .invalidEmail:
            print("invalidEmail")
        }
    } catch {
        print("Error:", error)
    }