定義
錯(cuò)誤處理是響應(yīng)錯(cuò)誤以及從錯(cuò)誤中回復(fù)的過程,那這個(gè)過程包括拋出、捕獲铡俐、傳遞和操作可恢復(fù)錯(cuò)誤的支持。
討論
有些操作可能無法在所有的狀態(tài)中都能返回一個(gè)有意義的值妥粟,當(dāng)然可選類型可以幫忙表示失敗的結(jié)果审丘,但是錯(cuò)誤處理可以讓你更好的理解錯(cuò)誤原因。
swift關(guān)于錯(cuò)誤處理的是協(xié)議Error勾给,這個(gè)是一個(gè)控協(xié)議滩报,可以通過枚舉和結(jié)構(gòu)體遵循這個(gè)協(xié)議來實(shí)現(xiàn)錯(cuò)誤處理。
swift的異常處理有四種方式
- 通過函數(shù)的方式傳遞下去
- do-try-catch方式捕獲
- try播急?將錯(cuò)誤作為可選性處理脓钾,錯(cuò)誤時(shí)返回nil。
- try桩警! 斷言錯(cuò)誤不會(huì)發(fā)生可训,但是如果發(fā)生了會(huì)有運(yùn)行時(shí)錯(cuò)誤。
例子
舉個(gè)自動(dòng)販賣機(jī)的例子捶枢。當(dāng)我們?nèi)プ詣?dòng)販賣機(jī)買東西的時(shí)候握截,可能遇到以下問題
enum VendingMachineError:Error{
case invalidSelection //選擇無效
case insufficientFunds(coinsNeeded:Int) //金額不足
case outOfStock //缺貨
}
接下來我們創(chuàng)建一個(gè)自動(dòng)販賣機(jī)類型
//商品結(jié)構(gòu)體
struct Item{
var price: Int
var count: Int
}
//自動(dòng)販賣機(jī)
class VendingMachine{
var inventory = [
"Candy Bar" : Item(price: 12, count: 7),
"Chips" : Item(price: 10, count: 4),
"Pretzels" : Item(price: 7, count: 4)
]
var coinsDesposited = 2
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 <= coinsDesposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price-coinsDesposited)
}
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("dispensing\(name)")
}
}
由上可知,我們分別檢驗(yàn)商品是否存在烂叔,庫(kù)存是否充足以及投幣是否足夠谨胞。如果不滿足就拋出異常。下面我們分別看一下上面說過的四種錯(cuò)誤處理方式蒜鸡。
可以看出在函數(shù)體后胯努,返回值之前添加throws關(guān)鍵字表明該方法可能拋出異常牢裳。
通過函數(shù)的方式傳遞下去
比如添加了一個(gè)購(gòu)買者姓名的屬性,通過try + 方法調(diào)用的方式可以將異常傳遞下去叶沛。
func vend(itemNamed name:String ,buyerName:String)throws{
self.buyerName = buyerName
try vend(itemNamed: name)
}
do-try-catch方式捕獲
var test = VendingMachine();
do {
try test.vend(itemNamed: "Chips")
} catch VendingMachineError.invalidSelection {
print("invalidSelection")
} catch VendingMachineError.outOfStock{
print("outOfStock")
} catch VendingMachineError.insufficientFunds(let coinsNeeded){
print("insufficientFunds\(coinsNeeded)")
}
通過do可以捕獲捕獲方法作用于內(nèi)拋出的異常蒲讯,catch可以以枚舉的方式處理。
try恬汁?將錯(cuò)誤作為可選性處理伶椿,錯(cuò)誤時(shí)返回nil。
let x = try? test.vend(itemNamed: "Chips")
通過try?的方式氓侧,當(dāng)排出異常的時(shí)候x值為nil脊另,正常可以返回一個(gè)可選型返回值约巷。
try偎痛! 斷言錯(cuò)誤不會(huì)發(fā)生,但是如果發(fā)生了會(huì)有運(yùn)行時(shí)錯(cuò)誤独郎。
let x = try踩麦! test.vend(itemNamed: "Chips")
當(dāng)我們斷言方法不會(huì)拋出異常的時(shí)候可以用try!拋出異常的時(shí)候會(huì)有運(yùn)行時(shí)錯(cuò)誤氓癌,比較危險(xiǎn)谓谦。
結(jié)構(gòu)體表示Error
有些時(shí)候我們要描述的錯(cuò)誤比較復(fù)雜,我們也可以用結(jié)構(gòu)體遵循Error協(xié)議去實(shí)現(xiàn)異常處理贪婉。
官方給出的例子,xml解析錯(cuò)誤
struct XMLParsingError: Error {
enum ErrorKind {
case invalidCharacter
case mismatchedTag
case internalError
}
let line: Int
let column: Int
let kind: ErrorKind
}
捕獲錯(cuò)誤
do {
let xmlDoc = try parse(myXMLData)
} catch let e as XMLParsingError {
print("Parsing error: \(e.kind) [\(e.line):\(e.column)]")
} catch {
print("Other error: \(error)")
}
綜上swift中的錯(cuò)誤處理是非常靈活的反粥,可以用多種數(shù)據(jù)結(jié)構(gòu)描述錯(cuò)誤。