Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to provide a localized 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?

like image 918
Evgenii Avatar asked Aug 27 '16 00:08

Evgenii


People also ask

How do I create a custom error in Swift?

To add a description to a new error type, extend the custom error to conform to CustomStringConvertible and add a property description : // For each error type return the appropriate description extension CustomError: CustomStringConvertible { public var description: String { switch self { case .

How do you convert error to NSError?

It should be possible to turn an arbitrary Swift enum that conforms to Error into an NSError by using the qualified type name as the domain key, the enumerator as the error code, and turning the payload into user data.


1 Answers

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.") 

By adopting the CustomNSError protocol the error can provide a 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 NSError  if let line = error.userInfo["line"] as? Int {     print("Error in line", line) // Error in line 13 }  print(error.code) // 999 print(error.domain) // myDomain 
like image 61
Martin R Avatar answered Sep 29 '22 11:09

Martin R