Swift错误处理
参考:
强制退出程序
使用assert
,表达式为假,程序强制退出
assert(1>0,"Error")
assert
还有一种形式为assertionFailure
,程序走到这个函数时,程序会直接终端,并打印中断的信息
assertionFailure("failure")
注意assert
和assertionFailure
都只在开发的过程中起作用,当release程序后,assert
和assertionFailure
就自动失效了。
不过有些时候,希望程序在真正执行起来的时候,在某些情况下,遇到一些严重的错误,程序要强制退出,可以使用precondition
和fatalError
precondition(1>0,"Error") fatalError("Error")
Error
在一般的处理过程中可以返回nil
表示错误,但是只返回nil
,不能表示出错的原因。比如连接网络,如果网络连接不上,就返回一个nil
,这样做也是可以的,但是此时只是知道网络没连接上而已。至于是服务端出错还是客户端出错,就不得而知了。所以需要一套完善的错误处理机制。
- 遵守
Error
协议
如下:
enum VendingError: Error{
case NoSuchItem
case NotEnoughMoney(Int)
case OutOfStock
}
2.抛出错误,使用throws
关键字,抛出错误后,整个函数就已经结束了,所以后面就不用return
了
真正抛出异常使用throw
关键字
func vend(itemName itemName: String,money: Int) throws -> Int{
guard let item = items[itemName] else{
throw VendingMachine.VendingError.NoSuchItem
}
guard money >= item.price else{
throw VendingMachine.VendingError.NotEnoughMoney(item.price)
}
guard item.count > 0 else{
throw VendingMachine.VendingError.OutOfStock
}
return money - item.price
}
}
1.正确的return
2.抛出异常
错误处理
对于抛出异常的函数,就不能直接调用了,要处理异常。使用try
关键字
try!
表示坚信函数不会抛出异常,但是这样写也是有风险的。
try! machine.vend(itemName: "Coca Cola",money: pocketMoney)
try?
表示如果抛出异常,返回值为nil
。所以对于返回值可以使用解包的形式:
if let leftMoney = try? machine.vend(itemName: "Coca Cola",money: pocketMoney)
{
}else{
}
如果希望更具错误的类型,来做不同的处理。就需要使用do
、catch
关键字,如下:
do{
pocketMoney = try machine.vend(itemName: "Coca Cola",money: pocketMoney)
print(pocketMoney,"Yuan left")
}catch{
print("Error occured during vending")
}
要处理不同类型的异常,形式如下:
do{
pocketMoney = try machine.vend(itemName: "Coca Cola",money: pocketMoney)
print(pocketMoney,"Yuan left")
}catch VendingMachine.VendingError.NoSuchItem{
print("No Such Item")
}catch VendingMachine.VendingError.NotEnoughMoney(let price){
print("No Enough Money",price,"Yuan needed.")
}catch VendingMachine.VendingError.OutOfStock{
print("Out of Stock")
}catch{
print("Error occured during vending.")
}
还有一种形式是:
do{
pocketMoney = try machine.vend(itemName: "Coca Cola","Yuan left")
}catch let error as VendingMachine.VendingError{
}catch{
print("Error occured during vending.")
}
defer
在其它语言中,错误处理通常有个finally
关键字,不管程序是否抛出异常,finally
中的代码都要执行。
在swift
中引入了defer
,它应该写在有可能退出这个函数的语句之前。defer
本身的意识是延迟,表示延迟执行。
func vend(itemName itemName: String,money: Int) throws -> Int{
defer {
print("Hava a nice day")
}
guard let item = items[itemName] else{
throw VendingMachine.VendingError.NoSuchItem
}
......
}
如果有多个defer,是按倒序来执行的,如下的方法:
func vend(itemName itemName: String,money: Int) throws -> Int{
defer {
print("Hava a nice day")
}
guard let item = items[itemName] else{
throw VendingMachine.VendingError.NoSuchItem
}
guard money >= item.price else{
throw VendingMachine.VendingError.NotEnoughMoney(item.price)
}
guard item.count > 0 else{
throw VendingMachine.VendingError.OutOfStock
}
defer {
print("Thank you")
}
dispenseItem(itemName: itemName)
return money - item.price
}
private func dispenseItem(itemName: String){
items[itemName]!.count -= 1
print("Enjoy your",itemName)
}
var pocketMoney = 3
try? machine.vend(itemName: "Coca Cola",money: pocketMoney)
则其输出顺序为:
Enjoy your Coca Cola Thank you Hava a nice day
var pocketMoney = 2
try? machine.vend(itemName: "Coca Cola",money: pocketMoney)
则控制台只会输出:
Hava a nice day
这是因为抛出异常结束程序,只会找抛出异常之前的defer
语句