1、Swift入门学习笔记(第一版),对Swift的基础知识点进行梳理总结。知识点一直在变,只是作为参考,以苹果官方文档为准~
2、在学习完基本的知识点以后会结合官方文档及相关资料,在此版本的基础上进行添加更改。
十八、错误处理
响应错误以及从错误中恢复的过程,在运行时可恢复错误抛出,捕获,传送和操作的高级支持
1、表示并抛出错误
错误遵循ErrorType
协议的值来表示,可用枚举列出错误情景
- enum VendingMachineError: ErrorType {
- case InvalidSelection //选择无效
- case InsufficientFunds(coinsNeeded: Int) //金额不足
- case OutOfStock //缺货
- }
使用throw关键字抛出
- throw VendingMachineError.OutOfStock
2、处理错误
Swift提供四种方式:
a、把函数抛出的错误传递给调用此函数的代码
b、用do-catch语句处理错误
c、将错误作为可选类型处理
d、断言此错误根本不会发生
2.1、用throwing函数传递错误
- func canThrowsErrors() throws -> String
throwing
函数从其内部抛出错误,并传递到该函数被调用时所在的区域中
- 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 var 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 //存款减去费用
- --item.count //存货减一
- inventory[name] = item
- dispenseSnack(name) //调函数说明正在分发物品
- }
- }
根据上面的描述可看出,vend(itemNamed:)
可能抛出错误
使用try
传递,try
后面跟可能发生错误的区域
定义属性
- var vend = VendingMachine()
- vend.coinsDeposited = 1
- try vend.vend(itemNamed: "Chips")
Output:
- 错误处理.VendingMachineError.InsufficientFunds(9)
- vend.coinsDeposited = 100
- try vend.vend(itemNamed: "Chip")
Output:
- 错误处理.VendingMachineError.InvalidSelection
其他错误就不一一演示了~验证起来十分简单
2.2、用Do-Catch处理错误
- var vend = VendingMachine() vend.coinsDeposited = 100
- do {
- try vend.vend(itemNamed: "Chips")
- } 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.")
- }
Output:
- Dispensing Chips
2.3、将错误转换为可选值
如果抛出错误,那么这个表达式为nil
,否则,即正常情况就是函数的返回值
- func someThrowingFunction() throws -> Int {
- // ...
- }
-
- let x = try? someThrowingFunction()
-
- let y: Int?
- do {
- y = try someThrowingFunction()
- } catch {
- y = nil
- }
但是不管正不正常,x、y都是可选类型
- let result = try?vend.vend(itemNamed: "XXX")
- print(result) //结果是nil,因为货物不在清单中
Output:
- nil
2.4、使错误传递失效
除try?
外还有try!
处理错误情况,但是try!
是确定没错的情况下值为函数返回值,如果出错直接崩溃。错误不会抛给catch
处理或向上抛出
3、指定清理操作
defer
语句,代码执行要离开当前代码段之前执行的一套语句。不管以何种方式离开(错误或return
或break
等),都会去执行的一些必要的清理工作
defer
关键字与要被延迟执行的语句组成
延迟执行操作是按照被指定的相反顺序执行的,譬如有两个defer
语句,那么第一条defer
在第二条defer
执行之后执行
这里的功能有点类似OC中异常处理机制中的finally
关键字
- func testDefer() throws {
- print("111111")
- defer {
- print("Defer1")
- }
- print("222222")
- defer {
- print("Defer2")
- }
- print("333333")
-
- do {
- defer {
- print("Do-Catch Defer")
- }
-
- try vend.vend(itemNamed: "chippppp")
- } 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.")
- }
-
- }
- try testDefer()
Output:
- 111111
- 222222
- 333333
- Do-Catch Defer
- Invalid Selection.
- Defer2
- Defer1
注意打印顺序,尤其Do-Catch
中的打印顺序,defer
语句先于catch
打印,可能defer
离开代码段之前的意思可能是外层{ }
,不知道这样理解对不对
如果把do中的代码顺序换下
- do {
- try vend.vend(itemNamed: "chippppp")
- defer {
- print("Do-Catch Defer")
- }
- }
Output:
- 111111
- 222222
- 333333
- Invalid Selection.
- Defer2
- Defer1
会发现do
中defer
语句根本没有执行,没有打印结果,这点在以后的应用中要注意