【问题标题】:In Objective C/Swift what do return within a method when an error is thrown?在Objective C / Swift中,当抛出错误时,方法中会返回什么?
【发布时间】:2014-09-12 04:44:23
【问题描述】:

注意:我在这篇文章的标题中说 Objective C/Swift 是因为我相信这个问题的答案将适用于这两种语言,但我在这篇文章中包含的代码是 Swift。

Java 有一个很好的异常处理机制,但在 Objective C 中,我们要么从委托方法返回错误,要么通过引用将错误传递给函数,然后再检查它。我想知道,当抛出错误时,从期望返回值(例如 NSString、UIImage 或其他一些复杂对象)的方法返回的最干净的方法是什么?我不知道“抛出”是否是在 Objective C 中使用的正确词,但我的意思是当您进行返回非零 NSError 的调用时。

例如,假设我有这段代码试图创建一个二维码的 UIImage:

func createQRImageWithString(string: String, andWidth width: Int32, andHeight height: Int32) -> UIImage {
    var error : NSError?
    let writer : ZXMultiFormatWriter = ZXMultiFormatWriter()
    let result = writer.encode(string, format: kBarcodeFormatQRCode, width: width, height: height, error: &error)
    if (error) {
        println(error!.localizedDescription)

    } else {
        let image :CGImageRef = ZXImage(matrix: result).cgimage
        return UIImage(CGImage: image)
    }
}

此函数无法编译,因为在 if 语句中没有返回 UIImage 对象。 func 在 func 和使用它的任何人之间创建一个合同,承诺将返回一个 UIImage。如果发生错误,我没有 UIImage 可以返回。我想我可以制作一个虚拟的空 UIImage 并返回它,但这肯定不是预期的。那么处理这个问题的最佳方法是什么?

我给出了一个使用 UIImage 的示例,但我希望答案可以推广到方法承诺返回对象但由于无法预料的错误返回该对象不会按计划进行的任何情况。

【问题讨论】:

  • 出于兴趣,你会用 Java 做什么?或者 Swift did 是否有异常处理?
  • 在Objective-C中不测试NSErrorout变量来判断是否发生错误,如果没有错误则不保证为0。而是测试该方法是否有错误,如果有错误,则从 out 错误变量中获取错误详细信息。这适用于调用 Objective-C API 的 Swift。
  • Objective-C 确实有异常,但将它们保留用于编程错误,而不是程序控制。由于 Swift 调用 Objective-C API,因此基本上适用相同的规则。问题是不能保证 Objective-C 异常可以跨堆栈帧处理异常。
  • @Zaph 所说的“测试方法是否有错误”你的意思是不是将“错误”传递给 if 语句,我应该传递方法的返回值(在这种情况下是“结果”)?
  • 在 Objective-C 中(参见特定文档),如果出现错误,该方法将返回 nil。这表明发生了错误。然后从out error参数中获取错误信息。 out error 参数不用于指示错误(有少数例外,再次奖励方法上的文档),即使没有错误也可能被方法修改。

标签: ios objective-c error-handling swift


【解决方案1】:

在 swift 中,您可以使用可选类型并返回 UIImage?,这允许您返回 UIImagenil

编译器将静态强制客户端处理可选的返回值,因此这是一种安全的方法,而不是在 Objective-C 中简单地返回 nil(即 NULL 指针)。

【讨论】:

  • 太棒了,当我有能力时,我会接受这个作为答案。 Swift 的 Optional 现在对我来说更有意义了。你知道 Optionals 的这个用例是否是它们背后的主要目的。它们是 Apple 版本的异常处理吗?
  • 好吧,我不确定它们是否是它们背后的主要目的,但它确实迫使人们以一种连贯和有计划的方式思考无效值......
  • 可选数据类型在函数式语言中相当普遍(参见 Haskell Maybe 类型或 Scala Option 类型),是的,与其他机制一起,它们比常规数据流的异常处理更受欢迎。请记住,仅 Optionals 不足以处理错误,例如您不知道导致错误的原因。在其他语言中,我们有针对这种情况的其他构造(如 Scala 中的 Try[T]),但在 swift 中,您可能会使用经典的 Cocoa 模式,即取出类型为 NSError 的参数,并填充适当的错误。
  • @RobNapier 是的,这就是我使用“模仿”的原因。 Try 也是 Scala 中的一元抽象,这使得它绝对比普通标记的联合更强大。是的,我们在 2.10 中得到了它 :)
  • @David 返回一个元组是个坏主意。您想返回两者中的任何一个,并且永远不要同时返回。带标签的联合(swift 中的类型化枚举)绝对是更合适的选择。
【解决方案2】:

一个答案是返回 UIImage? 而不是 UIImage,如果您没有要返回的图像,则返回 nil。然后,您的调用代码必须确定如果您没有图像该怎么做。如果可能没有图像,那么UIImage 可能不是您调用代码的正确“合同”,而UIImage? 是。

【讨论】:

  • 与@Gabriele Petronnela 提出的问题相同
【解决方案3】:

在 Objective-C 中,抛出异常是为编程错误保留的(很少有异常)。斯威夫特没有例外。 Swift 的设计者似乎已经决定,虽然有异常似乎是个好主意,但实际上并非如此。 (并且有大量带有异常处理的 Java 代码)。

如果发生错误,您的函数应返回指示发生错误的结果,并将错误变量设置为错误描述。如果您的函数调用另一个返回错误的函数,那么您需要确定被调用函数的错误是否表明您的函数返回错误。例如,一个检查 WiFi 是否可用的函数可能会调用一个在没有 WiFi 时产生错误的函数,在这种情况下,您的函数将返回没有 WiFi——而不提示存在错误。

如果被调用函数中的错误意味着您的函数本身失败,则适用相同的规则:返回一个表明存在错误的结果,并设置一个错误变量。在 Objective-C 中,方法通常返回 YES 表示成功,NO 表示失败,或者 nil 表示失败,not-nil 表示成功。在 Swift 中,您通常返回一个可选值。

【讨论】:

    猜你喜欢
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多