基本用法
| 12
 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
 
 | import UIKit
 enum PersonErrorType : ErrorType {
 case OutOfMaxBooks(required: Int)
 case lessThanZero
 }
 
 class Person: NSObject {
 
 private let maximumBooks = 1000
 private var books : Int = 0
 
 override var description : String {
 return "书柜当前还有\(books)本书"
 }
 
 func purchaseBooks(count: Int) throws {
 if books + count > maximumBooks {
 let required = (books + count) - maximumBooks
 throw PersonErrorType.OutOfMaxBooks(required: required)
 }
 books += count
 }
 
 func lendBooks(count: Int) throws {
 if count > books {
 throw PersonErrorType.lessThanZero
 }
 books -= count
 }
 
 func beginReceipt() {
 print("又要开始大采买了,真是爽啊")
 }
 
 func endReceipt() {
 print("购物结束,该去剁手去了")
 }
 
 class func person() -> Person {
 let person = Person()
 try! person.purchaseBooks(100)
 return person
 }
 
 
 }
 
 | 
这段代码很简单,而且没有用到错误处理,接着我们将这段代码改造一下,让它能使用错误处理
首先,定义一个错误处理类型,在 import 下面添加如下代码:
| 12
 3
 4
 
 | enum PersonErrorType : ErrorType {case OutOfMaxBooks(required: Int)
 case OutOfBooks
 }
 
 | 
定义一个枚举,遵守 ErrorType 协议,提供两个错误状态,同时为 OutOfMaxBooks 提供一个关联值,用来指出超出了几本书
接着将买书和借书的方法修改成如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | func purchaseBooks(count: Int) {if books + count > maximumBooks {
 let required = (books + count) - maximumBooks
 throw PersonErrorType.OutOfMaxBooks(required: required)
 }
 books += count
 }
 
 func lendBooks(count: Int) {
 if count > books {
 throw PersonErrorType.lessThanZero
 }
 books -= count
 }
 
 | 
在上面的代码中,使用关键字 throws 用来抛出异常,使用 try 来捕获异常。
接下来,进行测试
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | import UIKit
 class ViewController: UIViewController {
 
 override func viewDidLoad() {
 super.viewDidLoad()
 let person = Person.person()
 do {
 try person.purchaseBooks(1500)
 } catch PersonErrorType.OutOfMaxBooks(let required) {
 print("书柜满啦,新买的书放不下咯。还差\(required)个空位,赶紧买个新书柜吧")
 } catch {
 
 }
 
 do {
 try person.lendBooks(10000)
 } catch PersonErrorType.lessThanZero {
 print("你都没有书啦")
 } catch {
 
 }
 }
 }
 
 | 
打印结果如下:
swift 配合异常处理的两个新关键字
 guard 和 defer
我们为了说明 guard 和 defer 的作用,再定义两个方法 beginReceipt() 和 endReceipt() 
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | do {person.beginReceipt()
 try person.purchaseBooks(1500)
 person.endReceipt()
 } catch PersonErrorType.OutOfMaxBooks(let required) {
 print("书柜满啦,新买的书放不下咯。还差\(required)个空位,赶紧买个新书柜吧")
 } catch {
 
 }
 
 | 
只有前面一个函数的信息被打印出来了,因为执行 purchaseBooks 方法的时候抛出了错误,程序转移到了 catch 的代码块中,第二个函数没有获得执行的机会了。
这里就可以使用 defer 关键字
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | do {person.beginReceipt()
 defer {
 person.endReceipt()
 }
 
 try person.purchaseBooks(1500)
 
 } catch PersonErrorType.OutOfMaxBooks(let required) {
 print("书柜满啦,新买的书放不下咯。还差\(required)个空位,赶紧买个新书柜吧")
 } catch {
 
 }
 
 
 
 
 
 
 
 | 
这里,就可以使用 defer 来让 endReceipt 在 do 的作用域结束之前得到调用。
guard 就像一个坚盾,判断条件是否满足,不判组就抛出异常。满足后再让代码往下执行,如果此时判断条件中有可选类型,可以使用 guard 将可选类型解绑,具体见 guard
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | func purchaseBooks(count: Int) throws {guard books + count < maximumBooks else {
 let required = (books + count) - maximumBooks
 throw PersonErrorType.OutOfMaxBooks(required: required)
 }
 books += count
 }
 
 func lendBooks(count: Int) throws {
 guard count < books else {
 throw PersonErrorType.lessThanZero
 }
 books -= count
 }
 
 |