I am using a 3rd party SDK in one of my apps which implements custom error handling. And, unfortunately, they do not expose their error definitions. I want to be able to parse the underlying error.
The problem is that they obfuscate this by nesting the underlying error within the associated value, rather than exposing it through user info. Here is an example of an error I may get:
ZendeskSDK.ZendeskError.failedToInitialize(error: Optional(ZendeskSDKHTTPClient.HTTPError.requestFailed(error: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo=`...
I was wondering if it is at all possible to somehow get the associated value of this error without having access to ZendeskSDK.ZendeskError
?
I could of course do some string comparisons, but I would like to avoid it.
You can use a Mirror
to get the associated values. There are mostly 3 cases:
enum Foo {
case x(a: Int) // the value will be under the path ("x", "a")
case y(Int) // the value will be under the path ("y")
case z(Int, Int) // the values will be under the paths ("z", 0) and ("z", 1)
}
e.g.
let unknownValue: Any = Foo.x(a: 42)
let mirror = Mirror(reflecting: unknownValue)
print(mirror.descendant("x", "a")!)
In your case it seems like you can do mirror.descendant("requestFailed", "error")
, based on the output you provided.
If you don't know the names of the enum cases and associated values, you can try doing a search in the mirror's children
extension Mirror.Children {
func findErrorInAssociatedValues() -> (any Error)? {
// Since the associated could be one level deep or two levels deep, search up to two levels
for (_, child) in self {
if let error = child as? any Error {
return error
}
for (_, grandchild) in Mirror(reflecting: child).children {
if let error = grandchild as? any Error {
return error
}
}
}
return nil
}
}
// usage: mirror.children.findErrorInAssociatedValues()
Note that if the enum happens to conform to CustomReflectable
, it will have a custom mirror, and the value you want may not be in there. It's unlikely, but is a possibility nonetheless.