if (abc as? MySpecialType) == .mySpecialValue {
...
}
Is there a way to extend either the type of "abc" or MySpecialType so that it understands how to do this conversion?
My specific use-case is that I'm defining a swift error type (enum conforming to LocalizedError), but this is in the middle of some low-level network stack, which ends up getting converted to an NSURLError to the application (I have no control over this). So when I try to do as?, it always returns false. Instead, I'm forced initialize like so:
if MySpecialFailure(error: error) == . failureCase1 {
...
}
With a bit of an ugly initializer like this:
MySpecialFailure: LocalizedError {
case failureCase1
case failureCase2
public init?(error: Error) {
if let failure = error as? MySpecialFailure {
self = failure
} else if let failure = MySpecialFailure(error: error as NSError) {
self = failure
} else {
return nil
}
}
public init?(error: NSError) {
let convertableFailures: [MySpecialFailure] = [. failureCase1, . failureCase2]
for failure in convertableFailures {
let nsError = failure as NSError
if error.domain == nsError.domain,
error.code == nsError.code
{
self = failure
return
}
}
return nil
}
Any thoughts on a better approach? To reiterate, ideally I'd like this to work:
if (error as? MySpecialFailure) == .failureCase1 {
...
}
No, there is no public feature in Swift to customize the behavior of as?—the use of a failable converting initializer as you've done here is essentially how this operation is expected to be spelled (though the API guidelines would tell you to drop the label error:); @somu shows one way how one might simplify the implementation with a switch statement.
Thanks, I figured as much, just wanted to confirm. This is one of those weird cases I think where a Swift Error object is converted to an Objective-C NSError object (by the underlying stack), but then returned back to a Swift function where I actually want the original Swift Error object.
Thanks. The reason I opted for the loop rather than an explicit switch as you have here is because I actually don't know what the "code" values should be. I believe it's automatically converted in order, such that "failureCase1" has a code of 1, "failureCase2" has a code of 2, etc. But I did not want to rely on that. In addition it would be a hard bug to catch if someone were to reorder the enum.
In addition, "domain" appears to be autogenerated as a combination of "SPM Package Name.Library Name". So I also did not want to make any assumptions that that implementation would change either.