3

I've an error class that is:

public enum ModelError: Error {
  case invalidArray(model: String)

  var localizedDescription: String {
    switch self {
    case .invalidArray(model: let model):
      return "\(model) has an invalid array"
    default:
      return "modelError"
    }
  }
}

and when passed as an Error in a callback function, I want to access its custom localizedDescription. For instance:

func report(_ error: Error) {
  print("Error report: \(error.localizedDescription)")
}

But calling report(ModelError.invalidArray(model: "test")) prints:

"The operation couldn’t be completed. (ModelError error 0.)"

Such things seems feasible with NSError since I can override the localizedDescription property there. But I don't want to use NSError since it's not really a swift thing and a lot of libraries work with Error.

Guig
  • 9,891
  • 7
  • 64
  • 126
  • 1
    Shouldn't `ModelError(model: "test")` be `ModelError.invalidArray(model: "text")` ? – rmaddy Nov 10 '16 at 23:53
  • yes, bad copy paste. Thanks! – Guig Nov 11 '16 at 00:05
  • 1
    I can make your code work if `ModelError` conforms to `CustomStringConvertible` and `localizeDescription` is renamed to `description`. And then print `error` instead of `error.localizedDescription`. – rmaddy Nov 11 '16 at 00:07
  • @rmaddy Isn't that kind of outside the bounds of CustomStringConvertible? – GetSwifty Nov 11 '16 at 00:08
  • @PEEJWEEJ I don't know, is it? I thought that protocol can be used by anything that wants to provide a `description` method. I'm still learning Swift myself. – rmaddy Nov 11 '16 at 00:10
  • It can be, but the intention is that it describes the Type, not gives other info. https://developer.apple.com/reference/swift/customstringconvertible the description should be something like ModelError.invalidArray(test) – GetSwifty Nov 11 '16 at 00:11
  • but yeah, looks like this is a duplicate. Good to know – GetSwifty Nov 11 '16 at 00:13
  • Indeed, thanks and sorry for the duplicate – Guig Nov 11 '16 at 00:53

1 Answers1

1

According to the Documentation, localizedDescription is implemented in a protocol extension, not in the protocol declaration, which means there's nothing to adhere to or override. There is a type-wide interface for enums that adhere to Error.

My way I get around this is to use a wrapper protocol:

protocol LocalizedDescriptionError: Error {
    var localizedDescription: String { get }
}

public enum ModelError: LocalizedDescriptionError {
    case invalidArray(model: String)

    var localizedDescription: String {
        switch self {
        case .invalidArray(model: let model):
            return "\(model) has an invalid array"
        default:
            return "modelError"
        }
    }
}

let error: LocalizedDescriptionError = ModelError.invalidArray(model: "Model")
let text = error.localizedDescription // Model Has an invalid array
GetSwifty
  • 7,568
  • 1
  • 29
  • 46
  • 4
    The above works only because you are declaring the `error` constant to be of the (specialized) `LocalizedDescriptionError` type. If you allow it to be of the (base) `Error` type, it will dispatch to the default implementation within the `Error` protocol, since - as you mentioned - `localizedDescription` is not declared within the `Error` protocol itself and thus cannot be overridden. Must use the new `LocalizedError` protocol, instead. – Gary Jan 18 '17 at 16:18