Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override localizedDescription for custom Error in Swift 3? [duplicate]

Error protocol has only one property localizedDescription. I tried to create custom object inherited from NSObject and Error but I can not override localizedDescription. How can I do that?

This code does not allow me to get custom description:

class MyError: NSObject, Error {
    var desc = ""
    init(str: String) {
        desc = str
    }
    override var description: String {
        get {
            return "MyError: \(desc)"
        }
    }
   var localizedDescription: String {
        get {
            return self.description
        }
    }
}

func test_my_code() {
    let error = MyError(str: "my test string")
    let x = error as Error
    print(x.localizedDescription)
}

Calling function "test_my_code" get unexpected result: "The operation couldn’t be completed...".

What should I do to get result "MyError: my test string" ?

like image 712
Maxim Kholyavkin Avatar asked Dec 26 '16 03:12

Maxim Kholyavkin


People also ask

What is Localizeddescription Swift?

A string containing the localized description of the error.

What is error in Swift?

In Swift, errors are represented by values of types that conform to the Error protocol. This empty protocol indicates that a type can be used for error handling.


2 Answers

The documentation about new Error bridging feature is not clear enough still now, so this answer may need some updates in the near future, but according to SE-0112 and the latest Swift source code, you may need to use LocalizedError rather than Error and implement errorDescription.

class MyError: NSObject, LocalizedError {
    var desc = ""
    init(str: String) {
        desc = str
    }
    override var description: String {
        get {
            return "MyError: \(desc)"
        }
    }
    //You need to implement `errorDescription`, not `localizedDescription`.
    var errorDescription: String? {
        get {
            return self.description
        }
    }
}

func test_my_code() {
    let error = MyError(str: "my test string")
    let x = error as Error
    print(x.localizedDescription)
}
test_my_code() //->MyError: my test string

Other than using LocalizedError, this default implementation works:

(NSError.swift, the link shown above)

public extension Error {
    /// Retrieve the localized description for this error.
    var localizedDescription: String {
        return NSError(domain: _domain, code: _code, userInfo: nil).localizedDescription
    }
}

It is a little complicated how Swift defines _domain or _code from arbitrary types just conforming to Error, but it seems that NSError generates "The operation couldn’t be completed..." for unknown combinations of domain and code.

like image 126
OOPer Avatar answered Oct 13 '22 23:10

OOPer


If custom type conforms to protocol CustomStringConvertible and provides localized description, then the following extension of LocalizedError might be useful:

extension LocalizedError where Self: CustomStringConvertible {

   var errorDescription: String? {
      return description
   }
}

Example code:

class MyError: LocalizedError, CustomStringConvertible {

   let desc: String

   init(str: String) {
      desc = str
   }

   var description: String {
      let format = NSLocalizedString("Operation error: %@", comment: "Error description")
      return String.localizedStringWithFormat(format, desc)
   }
}


let error = MyError(str: "my test string")
let x = error as Error
print(x.localizedDescription) // Prints "Operation error: my test string"
print(String(describing: x))  // Prints "Operation error: my test string"
like image 35
Vlad Avatar answered Oct 13 '22 22:10

Vlad