首页 > 解决方案 > Swift 中的 NSError 和错误

问题描述

我已经看到关于 Swift 和 Swift 之间的区别已经存在一个问题,知道这些区别。但是,我不理解下面代码片段的行为,因为它编译正确。Swift 的错误处理机制要求每个没有出现在带有 throws 子句的函数中的 do-catch 块都包含一个通用处理程序(没有其他内容或for Error)。但是,似乎 using具有相同的效果。这里有人知道原因吗?我在另一个问题中读到“任何符合 ErrorType 的类都可以转换为 NSError。这些功能在文档中进行了描述。”。但是,文档NSErrorErrorcatchcatchNSError该答案所指出的并没有向我澄清这一点,因为它侧重于我没有使用的 Objective-C。

import Foundation
extension Int : Error {}
extension String : Error {}

func fErr() throws {
  let a = Int(readLine()!)!
  if a > 20 {
    throw 42
  } else {
    throw "An error occurred"
  }
}

func gErr() {
  do {
    try fErr()
  } catch let e as NSError {
    print(e)
  }
}

标签: swifterror-handlingnserrordo-catch

解决方案


在 Darwin 平台(macOS、iOS、tvOS、watchOS)上,Swift 有一个称为桥接的概念,它允许标准库提供的 Swift 类型接到 Objective-C 类型(通常由 Cocoa 框架提供)。执行此操作的类型包括

  • Array↔︎NSArray
  • Dictionary↔︎NSDictionary
  • Set↔︎NSSet
  • Error↔︎NSError
  • 等(有关更全面的列表,请参阅上面的链接)

桥接类型需要编译器支持,而Error↔︎NSError桥接有很多组件 其他外)。但是,这种桥接允许编译器通常将s 视为s,反之亦然;事实上,正如您在上面的片段中看到的那样,any可以转换为 an并返回。 NSErrorError ErrorNSError

您可以在我关于 custom NSErrors的另一个答案中看到实现这一点所需的一些运行时组件,但要点是任何Error都可以提供足够的信息来封装在一个NSError实例中(通过实现var _domainvar _codevar _userInfo),反之亦然.

当你发现一个错误as NSError时,你隐式地将Error(无论它是什么)桥接到一个NSError,就像你可以桥接[1, 2, 3] as NSArray或一样["foo" : "bar"] as NSDictionary

[请注意,桥接目前仅在 Objective-C 运行时可用的情况下可用,即仅在 Darwin 平台上可用。这种桥接调用在 Linux 上不起作用。]

另请参阅SE-0112 改进的 NSError 桥接(原始 Swift Evolution 提案)以获取更多背景信息和更多细节。


推荐阅读