Let me prefix with why I think this is not a duplicate of How to provide a localized description with an Error type in Swift?
The answers provided will still result in some static/class function call and not an initializer style or require casting to NSError (which I like to avoid).
A brief summery of the reasons:
A Swift function that throws
does not declare the error type. We cannot enforce the catch
to pass a custom type that simply conforms to the Error
protocol. Knowing that, on the do-catch side, we get no help from the compiler as to what type (if custom) of error we get and by default we'll expect the known NSError
properties. Otherwise, we need to simply rely on textual documentations explaining the type of errors we can catch, as the catch will simply pass an Error
type.
Now, unlike NSError, Error is a protocol where the properties we get in userInfo
are read only. So we resort to constructing an NSError type, and casting it as Error.
I am trying to create a simple clean struct that return an Error type (not NSError) where I can throw like:
throw MYError(domain: "com.somthing.error", code: 0, userInfo: [NSLocalizedDescriptionKey : "Something bad happened"])
Main issue is that the only way to set the NSLocalizedDescriptionKey
, is by initializing an NSError object. Doing so will require casting to Error
type (which is something I'm trying to avoid).
I first tried to use extension Error {...
, but cannot use an initializer.
If I use a struct conforming to Error protocol (struct MyError: Error {...
), I still have the problem of localizedDescription
is get only.
What I use is actually something like:
struct MYError: Error {
static func with(domain: String = "com.somthing.error", code: Int = 0, localizedDescription: String) -> Error {
return NSError(domain: domain, code: code, userInfo: [NSLocalizedDescriptionKey : localizedDescription]) as Error
}
}
Which I can use like:
throw MYError.with(localizedDescription: "Some Error has happened")
Intuitively, I would expect a type like MYError
to just use an initializer MYError(domain:...
, not a static function.
The more Swifty way would be something like:
enum ErrorType: Error {
case one
case two
case three(with: String)
}
...
// In some function:
throw ErrorThrown.three(with: "Three!")
...
// Catch like:
catch ErrorType.three(let str) {
print("Error three: \(str)")
}
It is not clear if we're there yet. It seems that NSError is still much at play where I know I can expect to get a localizedDescription
an optional localizedFailureReason
and the familiar NSError properties.