Evgenii Evgenii - 24 days ago 8
iOS Question

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

I am defining a custom error type with Swift 3 syntax and I want to provide a user-friendly description of the error which is returned by the

localizedDescription
property of the
Error
object. How can I do it?

public enum MyError: Error {
case customError

var localizedDescription: String {
switch self {
case .customError:
return NSLocalizedString("A user-friendly description of the error.", comment: "My error")
}
}
}

let error: Error = MyError.customError
error.localizedDescription
// "The operation couldn’t be completed. (MyError error 0.)"


Is there a way for the
localizedDescription
to return my custom error description ("A user-friendly description of the error.")? Note that the error object here is of type
Error
and not
MyError
. I can, of course, cast the object to MyError

(error as? MyError)?.localizedDescription


but is there a way to make it work without casting to my error type?

Answer

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.customError
print(error.localizedDescription) // A user-friendly description of the error.

You can provide even more information if the error is converted to 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 NSError
print(error.localizedDescription)        // I failed.
print(error.localizedFailureReason)      // Optional("I don\'t know why.")
print(error.localizedRecoverySuggestion) // Optional("Switch it off and on again.")