Fork me on GitHub

以撸代码的形式学习Swift-18:错误处理(Error handling)

错误处理(Error handling)是响应错误以及从错误中恢复的过程。

1 表示并抛出错误

Error空协议表明该类型可以用于错误处理

1
2
3
4
5
6
enum VendingMachineError: Error {
case InvalidSelection //选择无效
case InsufficientFunds(coinsNeeded: Int) //金额不足
case OutOfStock //缺货
}
throw VendingMachineError.InsufficientFunds(coinsNeeded: 5)

2 处理错误

为了标识出代码中可能会抛出错误的地方,在调用一个能抛出错误的函数、方法或者构造器之前,加上 try 关键字,或者 try? 或 try!这种变体。

四个处理错误的方式:

  1. 用throwing函数传递错误

throwing函数: 在函数声明的参数列表之后加上 throws 关键字,为了表示一个函数、方法或构造器可以抛出错误。

1
2
func canThrowErrors() throws -> String
func cannotThrowErrors() -> String

一个 throwing 函数可以在其内部抛出错误,并将错误传递到函数被调用时的作用域。
只有 throwing 函数可以传递错误。任何在某个非throwing函数内部抛出的错误只能在函数内部处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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 dispenseSnack(snack: String) {
print("Dispensing \(snack)")
}
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
dispenseSnack(snack: name)
}
}
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)
}
// throwing构造器能像throwing函数一样传递错误。
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
  1. 用 Do-Catch 处理错误
1
2
3
4
5
6
7
8
9
10
11
12
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
} 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.")
}
// 打印 “Insufficient funds. Please insert an additional 2 coins.”
  1. 将错误转换成可选值

如果 someThrowingFunction() 抛出一个错误, x 和 y 的值是 nil,否则 x 和 y 的值就是该函数的返回值。
无论 someThrowingFunction() 的返回值类型是什么类型, x 和 y 都是这个类型的可选类型。
x,y的两种形式类似,try? 更简洁。

1
2
3
4
5
6
7
8
9
10
11
func someThrowingFunction() throws -> Int {
// ...
return 0
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
  1. 禁用错误传递

try! 禁止错误传递,如真有错误抛出,就出现运行错误。

let photo = try! loadImage("./Resources/John Appleseed.jpg")

3 指定清理操作

playground文件在andyRon/LearnSwift

坚持原创技术分享,您的支持将鼓励我继续创作!
  • 本文标题: 以撸代码的形式学习Swift-18:错误处理(Error handling)
  • 本文作者: AndyRon
  • 发布时间: 2017年07月06日 - 13:43
  • 最后更新: 2018年10月15日 - 18:37
  • 本文链接: http://andyron.com/2017/swift-18-error-handling.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!