表示和抛出错误 (Representing and Throwing Errors)
使用符合 Error 协议的类型值来表示错误, 而枚举很适合:
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}抛出错误:
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)处理错误 (Handling Errors)
传播错误 (Propagating Errors Using Throwing Functions)
使用 throw 标记一个可抛出错误的函数, 方法或初始化器:
func canThrowErrors() throws -> String如果没有该标记, 则必须在函数内部处理该错误.
函数 vend 会传播错误:
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
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)")
}
}调用 vend 的函数:
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels",
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vendingMachine.vend(itemNamed: snackName)
}需要使用 try 关键字
结构体中传播错误:
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}使用 Do-Catch (Handling Errors Using 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).")
}最后的 catch 用于处理意外情况
catch 中匹配多个错误:
func eat(item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
print("Invalid selection, out of stock, or not enough money.")
}
}转换错误为可选值 (Converting Errors to Optional Values)
使用 try? 表达式, 如果发生错误则计算结果为 nil:
func someThrowingFunction() throws -> Int {
// ...
}
let x = try? someThrowingFunction()等同于:
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}用于条件表达式:
func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}禁止错误传播 (Disabling Error Propagation)
使用 try! 来表示不会发生错误:
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")如果发生错误将会直接报错, 错误也不会被传播出去
指定清除动作 (Specifying Cleanup Actions)
使用 defer 将必要的清除动作包含在其中, 无论代码块是否正常退出都会执行
❤️ 感谢你的访问,欢迎留言交流!❤️