There seems to be a many ways to define an Error and and many ways to print the error. I've having trouble deciding what's the best way to do this. How has everyone been tackling this?
Here are the many ways I know to create and print errors:
As an Enum:
#1: Error
enum EnumError1: Error {
case a
}
print(EnumError1.a) // a
print(EnumError1.a.localizedDescription) // The operation couldn’t be completed. (__lldb_expr_81.EnumError error 0.)
#2: Error and CustomStringConvertible
enum EnumError2: Error, CustomStringConvertible {
case a
var description: String {
switch self {
case .a: return "AAA"
}
}
}
print(EnumError2.a) // AAA
print(EnumError2.a.description) // AAA
print(EnumError2.a.localizedDescription) // The operation couldn’t be completed. (__lldb_expr_242.EnumError2 error 0.)
#3: Error and localizedDescription
enum EnumError3: Error {
case a
var localizedDescription: String { // <-- available due to NSError bridging
switch self {
case .a: return "AAA"
}
}
}
print(EnumError3.a) // a
print(EnumError3.a.localizedDescription) // AAA
#4: LocalizedError and localizedDescription
enum EnumError4: LocalizedError {
case a
var errorDescription: String? {
switch self {
case .a: return "AAA"
}
}
}
print(EnumError4.a) // a
print(EnumError4.a.localizedDescription) // AAA
As a struct:
#1: Error
struct StructError1: Error {
let x: String
}
print(StructError1(x: "a")) // StructError1(x: "a")
print(StructError1(x: "a").localizedDescription) // The operation couldn’t be completed. (__lldb_expr_210.StructError1 error 1.)
#2: Error and CustomStringConvertible
struct StructError2: Error, CustomStringConvertible {
let x: String
var description: String {
"StructError2(x: \(x))"
}
}
print(StructError2(x: "a")) // StructError2(x: a)
print(StructError2(x: "a").description) // StructError2(x: a)
print(StructError2(x: "a").localizedDescription) // The operation couldn’t be completed. (__lldb_expr_231.StructError2 error 1.)
#3: Error and localizeDescription
struct StructError3: Error {
let x: String
var localizedDescription: String {
"StructError3(x: \(x))"
}
}
print(StructError3(x: "a")) // StructError3(x: "a")
print(StructError3(x: "a").localizedDescription) // StructError3(x: a)
#4: LocalizedError and localizedDescription
struct StructError4: LocalizedError {
let x: String
var errorDescription: String? {
"StructError4(x: \(x))"
}
}
print(StructError4(x: "a")) // StructError4(x: "a")
print(StructError4(x: "a").localizedDescription) // StructError4(x: a)
The above examples are the basic examples I am aware of. I prefer to print variables and description be called automatically, like most data types. I don't like having to special case errors, especially when it's so easy to just call print
or include the variable in another string "Failure: (error)". Lately, I've been doing more struct errors to include richer data instead of enums with various associated values. My app does have a lot of the variations of the above and I don't like needing to remember what the type is in order to be able to print it properly.