Swift 中的异常处理

基本用法

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
import UIKit

enum PersonErrorType : ErrorType {
case OutOfMaxBooks(required: Int)
case lessThanZero
}

class Person: NSObject {
// 一个人有很多书
private let maximumBooks = 1000 // 这个人最多有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 下面添加如下代码:

1
2
3
4
enum PersonErrorType : ErrorType {
case OutOfMaxBooks(required: Int)
case OutOfBooks
}

定义一个枚举,遵守 ErrorType 协议,提供两个错误状态,同时为 OutOfMaxBooks 提供一个关联值,用来指出超出了几本书

接着将买书和借书的方法修改成如下:

1
2
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 来捕获异常。
接下来,进行测试

1
2
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 {

}
}
}

打印结果如下:

1
2
// 书柜满啦,新买的书放不下咯。还差600个空位,赶紧买个新书柜吧
// 你都没有书啦

swift 配合异常处理的两个新关键字

guarddefer

我们为了说明 guard 和 defer 的作用,再定义两个方法 beginReceipt() 和 endReceipt()

1
2
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 关键字

1
2
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 {

}
// 打印信息:
/*
又要开始大采买了,真是爽啊
购物结束,该去剁手去了
书柜满啦,新买的书放不下咯。还差600个空位,赶紧买个新书柜吧
*/

这里,就可以使用 defer 来让 endReceipt 在 do 的作用域结束之前得到调用。

guard 就像一个坚盾,判断条件是否满足,不判组就抛出异常。满足后再让代码往下执行,如果此时判断条件中有可选类型,可以使用 guard 将可选类型解绑,具体见 guard

1
2
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
}
文章作者: Ammar
文章链接: http://lizhaoloveit.cn/2016/04/22/Swift-%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ammar's Blog
打赏
  • 微信
  • 支付宝

评论