在Crashlytics的Objective-c代码中有一个Error对象崩溃的问题,因为它不响应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
?
谢谢你,谢谢
3条答案
按热度按时间tktrz96b1#
NSError和Error之间的桥接性质有些奇怪。它们被桥接 * 用于通信目的 * --也就是说,它们可以在Swift和可可之间来回穿梭;来自可可 * 的错误是 * NSError(NSError采用Swift中的Error协议,以允许此);但是你声明为符合Error的
class
本身 * 不是 * NSError。因为它不响应
userInfo
如果你需要Swift Error类型携带
userInfo
信息以支持可可,那么你需要寻找CustomNSError协议。https://developer.apple.com/documentation/foundation/customnserror
waxmsbnn2#
这看起来像是一个bug,我把它归档为SR-14322。
根据SE-0112 Improved NSError Bridging
每个符合Error协议的类型都隐式地桥接到NSError。
这适用于结构和枚举类型,但显然不适用于类类型。
您可以将
class SwiftError: Error
替换为struct SwiftError: Error
来解决此问题。如果由于某种原因这是不可能的,那么下面的“技巧”在我的测试中起作用:字符串
编译 * 和 * 得到预期的结果:
型
kulphzqa3#
这可能与Error协议符合Sendable协议有关,而类类型(不是struct)符合Sendable有一些特殊要求,例如必须是final类等。