How to provide a localized description with an Error type in Swift? How to provide a localized description with an Error type in Swift? swift swift

How to provide a localized description with an Error type in Swift?


As described in the Xcode 8 beta 6 release notes,

Swift-defined error types can provide localized error descriptions by adopting the new LocalizedError protocol.

In your case:

public enum MyError: Error {    case customError}extension MyError: LocalizedError {    public var errorDescription: String? {        switch self {        case .customError:            return NSLocalizedString("A user-friendly description of the error.", comment: "My error")        }    }}let error: Error = MyError.customErrorprint(error.localizedDescription) // A user-friendly description of the error.

You can provide even more information if the error is convertedto NSError (which is always possible):

extension MyError : LocalizedError {    public var errorDescription: String? {        switch self {        case .customError:            return NSLocalizedString("I failed.", comment: "")        }    }    public var failureReason: String? {        switch self {        case .customError:            return NSLocalizedString("I don't know why.", comment: "")        }    }    public var recoverySuggestion: String? {        switch self {        case .customError:            return NSLocalizedString("Switch it off and on again.", comment: "")        }    }}let error = MyError.customError as NSErrorprint(error.localizedDescription)        // I failed.print(error.localizedFailureReason)      // Optional("I don\'t know why.")print(error.localizedRecoverySuggestion) // Optional("Switch it off and on again.")

By adopting the CustomNSError protocol the error can providea userInfo dictionary (and also a domain and code). Example:

extension MyError: CustomNSError {    public static var errorDomain: String {        return "myDomain"    }    public var errorCode: Int {        switch self {        case .customError:            return 999        }    }    public var errorUserInfo: [String : Any] {        switch self {        case .customError:            return [ "line": 13]        }    }}let error = MyError.customError as NSErrorif let line = error.userInfo["line"] as? Int {    print("Error in line", line) // Error in line 13}print(error.code) // 999print(error.domain) // myDomain


I would also add, if your error has parameters like this

enum NetworkError: LocalizedError {  case responseStatusError(status: Int, message: String)}

you can call these parameters in your localized description like this:

extension NetworkError {  public var errorDescription: String? {    switch self {    case .responseStatusError(status: let status, message: let message):      return "Error with status \(status) and message \(message) was thrown"  }}

You can even make this shorter like this:

extension NetworkError {  public var errorDescription: String? {    switch self {    case let .responseStatusError(status, message):      return "Error with status \(status) and message \(message) was thrown"  }}


There are now two Error-adopting protocols that your error type can adopt in order to provide additional information to Objective-C — LocalizedError and CustomNSError. Here's an example error that adopts both of them:

enum MyBetterError : CustomNSError, LocalizedError {    case oops    // domain    static var errorDomain : String { return "MyDomain" }    // code    var errorCode : Int { return -666 }    // userInfo    var errorUserInfo: [String : Any] { return ["Hey":"Ho"] };    // localizedDescription    var errorDescription: String? { return "This sucks" }    // localizedFailureReason    var failureReason: String? { return "Because it sucks" }    // localizedRecoverySuggestion    var recoverySuggestion: String? { return "Give up" }}