微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift 语言中的错误处理

如何解决Swift 语言中的错误处理

斯威夫特 2 & 3

Swift 2 中的情况发生了一些变化,因为有一个新的错误处理机制,它有点类似于异常,但在细节上有所不同。

1.指示错误可能性

如果函数/方法想要表明它可能会抛出错误,它应该包含throws这样的关键字

func summonDefaultDragon() throws -> Dragon

注意:函数实际上可以抛出的错误类型没有规范。 这个声明只是声明函数可以抛出任何实现 ErrorType 类型的实例,或者根本不抛出。

2.调用可能抛出错误函数

为了调用函数,你需要使用 try 关键字,像这样

try summonDefaultDragon()

这条线通常应该像这样存在 do-catch 块

do {
    let dragon = try summonDefaultDragon() 
} catch DragonError.dragonIsMissing {
    // Some specific-case error-handling
} catch DragonError.notEnoughMana(let manarequired) {
    // Other specific-case error-handlng
} catch {
    // Catch all error-handling
}

注意:catch 子句使用了 Swift 模式匹配的所有强大功能,因此您在这里非常灵活。

throws如果您从本身标有关键字的函数调用抛出函数,则您可能决定传播错误

func fulfill(quest: Quest) throws {
    let dragon = try summonDefaultDragon()
    quest.ride(dragon)
}

或者,您可以使用以下方法调用 throwing 函数try?

let dragonorNil = try? summonDefaultDragon()

这样,如果发生任何错误,您要么得到返回值,要么得到 nil。使用这种方式你不会得到错误对象。

这意味着您还可以结合try?有用的语句,例如:

if let dragon = try? summonDefaultDragon()

或者

guard let dragon = try? summonDefaultDragon() else { ... }

最后,您可以确定您知道错误实际上不会发生(例如,因为您已经检查了先决条件)并使用try!关键字:

let dragon = try! summonDefaultDragon()

如果函数确实抛出错误,那么您将在应用程序中收到运行时错误,并且应用程序将终止。

3. 抛出错误

为了抛出错误,您可以使用 throw 关键字这样

throw DragonError.dragonIsMissing

你可以抛出任何符合ErrorType协议的东西。对于初学者NSError,符合此协议,但您可能希望使用基于枚举的方法ErrorType,它使您能够对多个相关错误进行分组,可能还有额外的数据,像这样

enum DragonError: ErrorType {
    case dragonIsMissing
    case notEnoughMana(requiredMana: Int)
    ...
}

新的 Swift 2 和 3 错误机制与 Java/C#/C++ 样式异常的主要区别如下:

  • 语法有点不同:++ do-catchvs传统语法。try``defer``try-catch-finally
  • 异常处理在异常路径中的执行时间通常比在成功路径中要长得多。Swift 2.0 错误并非如此,成功路径和错误路径的成本大致相同。
  • 必须声明所有抛出错误代码,而可能从任何地方抛出异常。在 Java 命名法中,所有错误都是“检查异常”。但是,与 Java 相比,您不指定可能引发的错误
  • Swift 异常与 ObjC 异常不兼容。您的do-catch块不会捕获任何 NSException,反之亦然,因为您必须使用 ObjC。
  • Swift 异常与返回(用于返回函数)或(用于返回函数)并传递错误详细信息的 CocoaNSError方法约定兼容。false``Bool``nil``AnyObject``NSErrorPointer

作为简化错误处理的额外语法糖,还有两个概念

  • 延迟操作(使用defer关键字),它可以让您实现与 Java/C#/etc 中的 finally 块相同的效果
  • 保护语句(使用guard关键字),它让你编写的 if/else 代码比正常的错误检查/信号代码少一些。

斯威夫特 1

正如 Leandros 建议的处理运行时错误(如网络连接问题、解析数据、打开文件等),您应该NSError像在 ObjC 中那样使用,因为 Foundation、AppKit、UIKit 等以这种方式报告它们的错误。所以它更多的是框架而不是语言。

一个常用的模式是分隔成功/失败块,如 AFNetworking:

var sessionManager = AFHTTPSessionManager(baseURL: NSURL(string: "yavin4.yavin.planets"))
sessionManager.HEAD("/api/destoryDeathStar", parameters: xwingsquad,
    success: { (NSURLSessionDataTask) -> Void in
        println("Success")
    },
    failure:{ (NSURLSessionDataTask, NSError) -> Void in
        println("Failure")
    })

仍然是失败块经常收到NSError的实例,描述了错误

对于程序员错误(如数组元素的越界访问、传递给函数调用的无效参数等),您在 ObjC 中使用了异常。Swift 语言似乎没有任何语言支持异常(如throw, catch, 等关键字)。但是,正如文档所暗示的那样,它与 ObjC 在同一运行时运行,因此您仍然可以NSExceptions像这样抛出:

NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()

尽管您可以选择在 ObjC 代码中捕获异常,但您无法在纯 Swift 中捕获它们。

问题是您是否应该为程序员错误抛出异常,或者更确切地说使用 Apple 在语言指南中建议的断言。

解决方法

我对 Swift 的了解并不多,但我注意到的一件事是没有例外。那么他们如何在 Swift 中进行错误处理呢?有没有人发现任何与错误处理有关的东西?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。