throw和throws
enum PrinterError: Error {
case OutOfPaper
case NoToner
case OnFire
}
使用 throw 來拋出一個(gè)錯(cuò)誤并使用 throws 來表示一個(gè)可以拋出錯(cuò)誤的函
數(shù)。如果在函數(shù)中拋出一個(gè)錯(cuò)誤,這個(gè)函 數(shù)會(huì)立刻返回并且調(diào)用該函
數(shù)的代碼會(huì)進(jìn)行錯(cuò)誤處理;
func send(job: Int, toPrinter printerName: String) throws -> String {
if printerName == "Never Has Toner" {
throw PrinterError.noToner
}
return "Job sent"
}
處理錯(cuò)誤的方式
方式一:用throwing函數(shù)傳遞錯(cuò)誤
1:為了表示一個(gè)函數(shù)、方法或構(gòu)造器可以拋出錯(cuò)誤,在函數(shù)聲明的參數(shù)
列表之后加上throws關(guān)鍵字。一個(gè)標(biāo)有throws關(guān)鍵字的函數(shù)被稱作
throwing函數(shù)。如果這個(gè)函數(shù)指明了返回值類型,throws關(guān)鍵詞需要寫在
箭頭(->)的前面
2:throwing構(gòu)造器能像throwing函數(shù)一樣傳遞錯(cuò)誤
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
注意
只有throwing函數(shù)可以傳遞錯(cuò)誤。任何在某個(gè)非throwing函數(shù)內(nèi)部拋出
的錯(cuò)誤只能在函數(shù)內(nèi)部處理;
方式二:使用do - catch
do {
//在 do 代碼塊中,使用 try 來標(biāo)記可能拋出錯(cuò)誤 的代碼。
let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
print(printerResponse)
} catch {
在 catch 代碼塊中,除非你另外命名,否則錯(cuò)誤會(huì)自動(dòng)命名為 error ,
這里就是用來處理do里面代碼出現(xiàn)錯(cuò)誤的時(shí)候執(zhí)行的代碼;
print(error)
}
方式三:將錯(cuò)誤轉(zhuǎn)換成可選值
可以使用try?通過將錯(cuò)誤轉(zhuǎn)換成一個(gè)可選值來處理錯(cuò)誤。如果在評估
try?表達(dá)式時(shí)一個(gè)錯(cuò)誤被拋出,那么表達(dá)式的值就是nil;
func someThrowingFunction() throws -> Int {
// ...
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
這里x和y的處理是等效的;
方式四:禁用錯(cuò)誤傳遞
有時(shí)你知道某個(gè)throwing函數(shù)實(shí)際上在運(yùn)行時(shí)是不會(huì)拋出錯(cuò)誤的,在這
種情況下,你可以在表達(dá)式前面寫try!來禁用錯(cuò)誤傳遞,這會(huì)把調(diào)用包
裝在一個(gè)不會(huì)有錯(cuò)誤拋出的運(yùn)行時(shí)斷言中。如果真的拋出了錯(cuò)誤,你會(huì)
得到一個(gè)運(yùn)行時(shí)錯(cuò)誤;
延遲操作處理
可以使用defer語句在即將離開當(dāng)前代碼塊時(shí)執(zhí)行一系列語句。該語句讓
你能執(zhí)行一些必要的清理工作,不管是以何種方式離開當(dāng)前代碼塊的
——無論是由于拋出錯(cuò)誤而離開,還是由于諸如return或者break的語句
defer語句將代碼的執(zhí)行延遲到當(dāng)前的作用域退出之前。該語句由defer
關(guān)鍵字和要被延遲執(zhí)行的語句組成。延遲執(zhí)行的語句不能包含任何控制
轉(zhuǎn)移語句,例如break或是return語句,或是拋出一個(gè)錯(cuò)誤。延遲執(zhí)行的
操作會(huì) 按照它們被指定時(shí)的順序的相反順序執(zhí)行——也就是說,第一
條defer語句中的代碼會(huì)在第二條defer語句中的代碼被執(zhí)行之后才執(zhí)行;
例子
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() { // 處理文件。
}
// close(file) 會(huì)在這里被調(diào)用,即作用域的最后。
}