0

I'm trying to implement my own Error type by reading the Apple's document in Swift 3.

I have defined my error type like this:

enum MyError: Error {

  case unknown
  case offline
  case accountMissing

  var localizedDescription: String {

    switch self {
    case .unknown: return "Unknown Error"
    case .offline: return "Offline Error"
    case .accountMissing: return "Account Missing Error"
    }
  }
}

Then I have implemented a presenting function to display an error. (The arg error can be MyError or Error that are returned by system function.

func printError(_ error: Error) {
  print(error.localizedDescription) 
  // The operation couldn’t be completed. (MyError error 1.)
}

When MyError is passed to this function, for example printError(MyError.offline), I expected "Offline Error" as the result, but the results is

The operation couldn’t be completed. (MyError error 1.)

, not "Offline Error" as I expected. To get the expected results, I need to force cast like this:

print((error as! MyError).localizedDescription)

I don't understand why this happens. MyError type inherited Error protocol. Shouldn't the "error" act as MyError type without force casting?

(MyError is defined as enum here, but I also tried to define as a class. The results was the same.)

Is there a comprehensive way to display arbitrary Error types to users?


I'm confused with Error protocol. I expected func printError(_ error: Error) should have accepted anything that is conformed to Error protocol, and would print localizedDescription of MyError type's own implementation.

I still don't understand why these two results are different. I assume it is because MyError is not a class but it's still not clear for me. Could anyone give me clear explanation?

func printErrorA(_ error: Error) {
  print(error.localizedDescription)
}

func printErrorB(_ error: MyError) {
  print(error.localizedDescription)
}

printErrorA(MyError.offline) // <--
printErrorB(MyError.offline) // <--

Thank you @martinr

"Protocol extension members aren't class members so they can't be overridden by subclasses"

"protocol extension is statically dispatched"

Override of protocol default implementation in a subsubclass doesn't participate in dynamic dispatch

https://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future

After reading How to provide a localized description with an Error type in Swift? I re-wrote my code like this

enum MyError : LocalizedError {
  case unknown
  case offline
  case accountMissing
  var errorDescription: String? {
    switch self {
    case .unknown: return "Unknown Error"
    case .offline: return "Offline Error"
    case .accountMissing: return "Account Missing Error"
    }
  }
}

func printErrorA(_ error: Error) {
  print(error.localizedDescription)
}

func printErrorB(_ error: MyError) {
  print(error.localizedDescription)
}

printErrorA(MyError.offline) // <-- Offline Error
printErrorB(MyError.offline) // <-- Offline Error
Community
  • 1
  • 1
user5865651
  • 1,478
  • 1
  • 9
  • 11
  • 1
    You mean you want a function that can print both your error enum and the system NSError? – Tj3n Sep 15 '16 at 11:06
  • try this : `func printError(_ error: MyError)` – Bista Sep 15 '16 at 11:08
  • printError(_ error: MyError) does not accept Error type. – user5865651 Sep 15 '16 at 11:42
  • Yes, I need a way to accept both my custom error type and the system Error type. Also I want to know the reason why 'error' does not act as MyError unless force down casting. Seems contradicting polymorphism for me. – user5865651 Sep 15 '16 at 11:46
  • 1
    @user5865651: The linked-to Q&A http://stackoverflow.com/questions/39176196/how-to-provide-a-localised-description-with-an-error-type-in-swift should answer your question *how* to make it work. – As for why your method does not work, compare http://stackoverflow.com/questions/39007960/override-of-protocol-default-implementation-in-a-subsubclass-doesnt-participate/39008193#39008193 and the related questions. If a method is only defined as default implementation in a protocol extension then it is statically dispatched. – Martin R Sep 15 '16 at 12:26
  • (...cont.) Therefore `error.localizedDescription` calls the default implementation, and not that of your `MyError` type. – Martin R Sep 15 '16 at 12:27

0 Answers0