错误处理(Error handling)是响应错误以及从错误中恢复的过程。Swift 在运行时提供了对可恢复错误进行抛出、捕获、传递和操作等支持。
某些操作无法保证总是执行完所有代码或总是生成有用的结果。可选类型可用来表示值缺失,但是当某个操作失败时,理解造成失败的原因有助于你的代码作出相应的应对。
举个例子,假如有个从磁盘上的某个文件读取数据并进行处理的任务,该任务会有多种可能失败的情况,包括指定路径下文件并不存在,文件不具有可读权限,或者文件编码格式不兼容。区分这些不同的失败情况可以让程序解决并处理某些错误,然后把它解决不了的错误报告给用户。
表示与抛出错误
在 Swift 中,错误用遵循 Error 协议的类型的值来表示,这个空协议表明该类型可以用于错误处理。
Swift 的枚举类型尤为适合构建一组相关的错误状态,枚举的关联值还可以提供错误状态的额外信息。
例如,你可以这样表示在一个游戏中操作自动贩卖机时可能会出现的错误状态:
enum VendingMachineError: Error {
case invalidSelection //选择无效
case insufficientFunds(coinsNeeded: Int) //金额不足
case outOfStock //缺货
}
抛出一个错误可以让你表明有意外情况发生,导致正常的执行流程无法继续执行。抛出错误使用 throw 关键字。
例如,下面的代码抛出一个错误,提示贩卖机还需要 5 个硬币:
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
处理错误
某个错误被抛出时,附近的某部分代码必须负责处理这个错误,例如纠正这个问题、尝试其他方式、向用户报告错误。
Swift 中有4种处理错误的方式:
把函数抛出的错误传递给调用此函数的代码
用 do-catch 语句处理错误
将错误作为可选类型处理
断言此错误根本不会发生
当一个函数抛出一个错误时,你的程序流程会发生改变,所以重要的是你能迅速识别代码中会抛出错误的地方。为了标识出这些地方,在调用一个能抛出错误的函数、方法或构造器之前,加上 try 关键字,或 try? 或 try! 这种变体。
注意:
Swift 中的错误处理和其他语言中用 try,catch 和 throw 进行异常处理很像。和其他语言中(包括 Objective-C )的异常处理不同的是,Swift 中的错误处理并不涉及解除调用栈,这是一个计算代价高昂的过程。就此而言,throw 语句的性能特性是可以和 return 语句相媲美的。
用 throwing 函数传递错误
为了表示一个函数、方法或构造器可以抛出错误,在函数声明的参数列表之后加上throws关键字。一个标有 throws 关键字的函数被称作 throwing 函数。如果这个函数指明了返回值类型,throws 关键词需要写在箭头( -> )的前面。
func canThrowErrors() throws -> String {
return ""}
func cannotThrowErrors() -> String {
return ""}
一个 throwing 函数可以在其内部抛出错误,并将错误传递到函数被调用时的作用域。
注意:只有 throwing 函数可以传递错误,任何在某个非 throwing 函数内部抛出的错误只能在函数内部处理。
下面的例子中,VendingMachine 类有一个 vend(itemNamed:) 方法,如果请求的物品不存在、缺货或者投入金额小于物品价格,该方法就会抛出一个相应的 VendingMachineError:
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12,