We had an issue with an Error object that crashes in Crashlytics' Objective-c code because it doesn't respond to userInfo (a member of NSError), while investigating I stumbled upon this weird behavior in Swift.
In a playground, I tried creating a class SwiftError implementing the Error protocol:
class SwiftError: Error {
}
let sError = SwiftError()
if sError is NSError { // Generates a warning: 'is' test is always true
print("Success")
} else {
print("Fail")
}
// Prints Fail
let nsError = sError as NSError
//Compiler Error: 'SwiftError' is not convertible to 'NSError'; did you mean to use 'as!' to force downcast?
- Checking if the SwiftError is NSError gives a warning that it always succeeds but fails runtime.
- Casting SwiftError as an NSError gives a compiler error.
Can someone help explain to me why this happens and how could I know if a class implementing the Error protocol actually is an NSError or not ?
Thanks!
There is something odd about the nature of the bridging between NSError and Error. They are bridged for communication purposes — that is, they can travel back and forth between Swift and Cocoa; and an error that comes from Cocoa is an NSError (and NSError adopts the Error protocol in Swift, to allow for this); but your
classthat you declare as conforming to Error is itself not an NSError.If you need your Swift Error type to carry
userInfoinformation for Cocoa's benefit, then you were looking for the CustomNSError protocol.https://developer.apple.com/documentation/foundation/customnserror