1

I have a custom error type in my Swift project:

struct RuntimeError : LocalizedError {
    let localizedDescription: String
    init(_ str : String) {
        localizedDescription = str
    }
}

If it is raised at the top level, I get a message like this which is useful but not quite what I expected:

Fatal error: Error raised at top level: MyApp.RuntimeError(localizedDescription: "Error message…")

If I catch it and log its .localizedDescription, I don't even get a debug-like struct description but ± generic text instead!

E.g. the code

do {
  throw RuntimeError("Message")
} catch {
  NSLog("Caught error: %@", error.localizedDescription)
}

outputs only:

Caught error: The operation couldn’t be completed. (MyApp.RuntimeError error 1.)

If I change my log to (error as! RuntimeError).localizedDescription I get the expected string, but that's not a solution since in practice not all errors will be of this type.

Why isn't my struct's localizedDescription property used when accessed through the Error protocol? How can I create a custom Error or LocalizedError struct that always provides a custom message?

natevw
  • 16,807
  • 8
  • 66
  • 90
  • Is there a reason you're using ObjC's error api's rather than Swift's? – Alexander Apr 06 '18 at 17:18
  • @Alexander: There can be legitimate reasons to use `NSLog`. For example it writes to the device log, so you can inspect the messages later in Xcode. Also it is thread-safe (which `print` is not). – Martin R Apr 06 '18 at 17:22
  • In this case, my reason was old habits when typing up a quick example for this site. In my actual code I have a wrapper around `os_log`; but my issue in question is with `.localizedDescription` no matter where it is used. – natevw Apr 06 '18 at 17:30
  • 3
    I figured it out, and it matches the duplicate question links as well: instead of an instance variable `let localizedDescription: String` I needed to store my message in `let errorDescription: String?` instead. Note that it *must* be an optional String otherwise it still doesn't work — I think that's what tripped me up when using other examples earlier. – natevw Apr 06 '18 at 17:33
  • @MartinR I meant subclassing `Foundation.LocalizedError` over conforming to `Swift.Error` – Alexander Apr 06 '18 at 17:49
  • @Alexander: Then I misunderstood your comment! – But what are you thinking of as alternative? LocalizedError is a protocol as well (and inherits from Error), so this is not a subclass. – Martin R Apr 06 '18 at 17:55
  • @MartinR Oh interesting. I thought it was a subclass of NSError. Nevermind! – Alexander Apr 06 '18 at 18:01
  • Good question, I am faced with the same problem – Alexander Yakovlev Feb 10 '20 at 11:58

0 Answers0