Swift
错误处理
本文详细介绍了 Swift 中的错误处理机制,包括错误的表示与抛出、使用 throwing 函数传递错误、Do-Catch 捕获错误、将错误转换为可选值以及禁用错误传递。
错误处理(Error Handling)是响应错误并从中恢复的过程。Swift 提供了一流的错误处理支持,包括在运行时抛出、捕获、传递和操作可恢复错误。
表示与抛出错误
在 Swift 中,错误用符合 Error 协议的类型的值来表示。枚举特别适合构建一组相关的错误状态。
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)处理错误
fSwift 提供了四种处理错误的方式:
- 将错误传递给调用该函数的代码。
- 使用
do-catch语句处理错误。 - 将错误作为可选值处理。
- 断言此错误根本不会发生。
用 throwing 函数传递错误
为了表示一个函数、方法或构造器可以抛出错误,在参数列表后加上 throws 关键字。
func vend(itemNamed name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("Dispensing \(name)")
}使用 Do-Catch 处理错误
使用 do-catch 语句运行一段代码。如果 do 子句中的代码抛出了错误,它会与 catch 子句进行匹配,以确定哪一个可以处理该错误。
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
print("Success! Yum.")
} catch VendingMachineError.invalidSelection {
print("Invalid Selection.")
} catch VendingMachineError.outOfStock {
print("Out of Stock.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
} catch {
print("Unexpected error: \(error).")
}将错误转换成可选值
使用 try? 将错误转换为可选值。如果函数抛出错误,表达式的值为 nil。
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}禁用错误传递
如果你确定某个 throwing 函数在运行时不会抛出错误,可以使用 try!。这会将调用包装在运行时断言中,如果真的抛出错误,应用会崩溃。
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")指定清理操作
使用 defer 语句在代码执行离开当前代码块之前执行一组语句。无论代码是因为抛出错误还是正常返回离开,defer 中的代码都会执行。
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// 处理文件
}
// close(file) 会在这里被调用,就在作用域结束之前
}
}在 GitHub 上编辑
上次更新于