【问题标题】:NSError and Error in SwiftSwift 中的 NSError 和错误
【发布时间】:2018-10-05 04:59:16
【问题描述】:

我已经看到在 Swift 中 NSErrorError 之间的区别已经有一个 question,我知道这些区别。但是,我不理解下面代码 sn-p 的行为,因为它编译正确。 Swift 的错误处理机制要求没有出现在带有 throws 子句的函数中的每个 do-catch 块都包含一个通用处理程序(catch 没有其他内容,或者 catch 表示错误)。但是,使用NSError 似乎具有相同的效果。这里有人知道原因吗?我在another question 中读到“任何符合 ErrorType 的类都可以转换为 NSError。这些特性在文档中进行了描述。”。但是,该答案所指向的documentation 并未向我阐明这一点,因为它侧重于我没有使用的 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)
  }
}

【问题讨论】:

    标签: swift error-handling nserror do-catch


    【解决方案1】:

    在 Darwin 平台(macOS、iOS、tvOS、watchOS)上,Swift 有一个名为 bridging 的概念,它允许标准库提供的 Swift 类型到 Objective-C 类型(通常出售由 Cocoa 框架)。这样做的类型包括

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

    桥接类型需要编译器支持,Error↔︎NSError 桥接有quitea fewcomponents (among others)。但是,这种桥接允许编译器通常将NSErrors 视为Errors,反之亦然;事实上,正如您在上面的 sn-p 中看到的那样,any Error 可以转换为 NSError 并返回。

    您可以在another answer of mine on 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 Improved NSError Bridging(原始 Swift Evolution 提案)了解更多背景信息和详细信息。

    【讨论】:

    • 感谢您的详尽回答。关于在 Linux 上不起作用的桥接调用的部分确实引起了我的注意。去测试一下。
    【解决方案2】:

    正如我所见,Swift 源代码的某处存在隐式转换。

    可能的证明之一是 C++ code 的这一部分 Optional<SILDeclRef> ErrorToNSErrorFn;

    【讨论】:

      猜你喜欢
      • 2017-01-19
      • 2015-03-11
      • 1970-01-01
      • 1970-01-01
      • 2017-03-03
      • 2010-12-25
      • 2014-06-09
      • 2023-04-01
      • 2011-01-05
      相关资源
      最近更新 更多