Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Error Handling - Struct/Class vs Enum

I am trying to model the possible errors that can be returned by the API I'm consuming and also possible network errors.

I'm struggling to figure out if I should use the Struct/Class approach, where each type of error is modeled as a Struct/Class, or the Enum approach.

Here are some notes to take into consideration:

  1. Depending on what goes wrong, the same API call can return different errors with different media-types (so different JSON). So my errors have different properties. I don't want to expose the request response as a simple JSON Object / Dictionary.
  2. I want the errors caused by a Client/Server issue to have a httpStatusCode property as well (it will be nil for errors that are related to no connectivity)
  3. I want to have an error that indicates a connectivity issue with a proper localized message.
  4. I want to use the same errors for both sync calls (used with throws) and async calls (used as a parameter in the completion block)

Mainly because of the first requirement it's pretty hard to figure out how to go down the Enum way. But maybe I'm missing something, maybe there still is some power that lays in the Enum types that I am not aware of.

Any suggestions would be highly appreciated.

like image 211
Cosmin Avatar asked Oct 20 '25 14:10

Cosmin


1 Answers

Often enum is the best approach to deal with errors on Swift. To deliver different types you can use associated values and for a localized description you can implement LocalizedError protocol for your enum e.g:

enum NetworkError : Error, LocalizedError {
    case noInternet
    case httpStatus(Int)
    case unknown(Error)
    
    public var errorDescription: String? {
        switch self {
            case .noInternet:
                return "No Internet"
                
            case .httpStatus(let code):
                return "HTTP status code: \(code)"
                
            case .unknown(let error):
                return "Error: \(error)"
        }
    }
}

let err1 = NetworkError.noInternet
print(err1.localizedDescription)

let err2 = NetworkError.httpStatus(404)
print(err2.localizedDescription)

let err3 = NetworkError.unknown(error)
print(err3.localizedDescription)

/*
Prints:

No Internet
HTTP status code: 404
Error: error
*/

But if you have common data for your errors you should implement struct that holds needed properties with a type of your error:

struct ResponseError: Error {
    enum ErrorType {
        case badStatusCode
        case noJson
        case invalidJson(Error)
    }

    let type: ErrorType
    let statusCode: Int
}

let err = ResponseError(type: .badStatusCode, statusCode: 404)

Read more from the documentation about: https://developer.apple.com/documentation/swift/error

like image 60
iUrii Avatar answered Oct 22 '25 04:10

iUrii



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!