如何解决评估错误是否为 NSError 总是成功,而将错误转换为 NSError 会给出编译器错误
我们遇到了错误对象的问题,该对象在 Crashlytics 的 Objective-c 代码中崩溃,因为它不响应 userInfo
(NSError
的成员),在调查时我偶然发现了这个奇怪的问题Swift 中的行为。
在操场上,我尝试创建一个实现 SwiftError
协议的类 Error
:
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?
- 检查 SwiftError 是否为 NSError 会给出警告,表明它总是成功但在运行时失败。
- 将 SwiftError 转换为 NSError 会导致编译器错误。
有人可以帮我解释为什么会发生这种情况,我怎么知道实现 Error
协议的类实际上是否是 NSError
?
谢谢!
解决方法
NSError 和 Error 之间桥接的性质有些奇怪。它们被桥接用于通信目的——也就是说,它们可以在 Swift 和 Cocoa 之间来回移动;来自 Cocoa 的错误 是一个 NSError(并且 NSError 在 Swift 中采用了 Error 协议,以允许这一点);但是您声明为符合 Error 的 class
本身不是一个 NSError。
因为它不响应 userInfo
如果为了 Cocoa 的利益,您需要 Swift Error 类型携带 userInfo
信息,那么您正在寻找 CustomNSError 协议。
https://developer.apple.com/documentation/foundation/customnserror
,这在我看来像是一个错误,我已将其归档为 SR-14322。
根据SE-0112 Improved NSError Bridging,
每个符合 Error 协议的类型都隐式地桥接到 NSError。
这适用于结构和枚举类型,但显然不适用于类类型。
您可以用 class SwiftError: Error
替换您的 struct SwiftError: Error
来解决问题。如果由于某种原因这是不可能的,那么以下“技巧”在我的测试中起作用:
let nsError = sError as Error as NSError
编译并且给出了预期的结果:
class SwiftError: Error {}
extension SwiftError: CustomNSError {
public static var errorDomain: String { "MyDomain" }
public var errorCode: Int { 13 }
public var errorUserInfo: [String : Any] { ["Foo" : "Bar" ] }
}
let sError = SwiftError()
let nsError = sError as Error as NSError
print(nsError.userInfo)
// Output: ["Foo": "Bar"]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。