xcode 如果Error是NSError,则计算总是成功,而将Error强制转换为NSError则会给出编译器错误

3vpjnl9f  于 2023-08-07  发布在  其他
关注(0)|答案(3)|浏览(114)

在Crashlytics的Objective-c代码中有一个Error对象崩溃的问题,因为它不响应userInfoNSError的成员),我在调查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
谢谢你,谢谢

tktrz96b

tktrz96b1#

NSError和Error之间的桥接性质有些奇怪。它们被桥接 * 用于通信目的 * --也就是说,它们可以在Swift和可可之间来回穿梭;来自可可 * 的错误是 * NSError(NSError采用Swift中的Error协议,以允许此);但是你声明为符合Error的class本身 * 不是 * NSError。
因为它不响应userInfo
如果你需要Swift Error类型携带userInfo信息以支持可可,那么你需要寻找CustomNSError协议。
https://developer.apple.com/documentation/foundation/customnserror

waxmsbnn

waxmsbnn2#

这看起来像是一个bug,我把它归档为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"]

kulphzqa

kulphzqa3#

这可能与Error协议符合Sendable协议有关,而类类型(不是struct)符合Sendable有一些特殊要求,例如必须是final类等。

相关问题