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