Swift中throw
和rethrows
關(guān)鍵字用于異常處理(Error handling)貌虾,都是用在函數(shù)中,可以簡單理解為throw讓函數(shù)或者方法可能出現(xiàn)的異常得到處理(比如用do-catch處理)舔亭,而rethrows
只是傳遞throw
,本身沒有針對函數(shù)或方法崭倘,下面詳細(xì)解釋一下:
throw
throws
關(guān)鍵字首先用在函數(shù)申明中聊替,放在返回類型的前面,比如標(biāo)準(zhǔn)庫中map的函數(shù)簽名:
func map<T>(_ transform: (Int) throws -> T) rethrows -> [T]
然后在函數(shù)內(nèi)部开财,如果出現(xiàn)可能的異常汉柒,就可以throw這個異常误褪,通常可以用一個枚舉來代表一類異常碾褂,這個枚舉可以實現(xiàn)Error
協(xié)議兽间,比如:
enum TestError: Error {
case errorOne(Int)
case errorTwo(String)
case errorThree
case errorUnknown
}
func testThrow(num: Int) throws -> String {
switch num {
case 1:
throw TestError.errorOne(1)
case 2:
throw TestError.errorTwo("2")
case 3:
throw TestError.errorThree
case 4:
throw TestError.errorUnknown
default:
return "No Error"
}
}
這樣,通過throw函數(shù)中可能出現(xiàn)的異常斋扰,讓函數(shù)反饋錯誤渡八,強(qiáng)制調(diào)用這個函數(shù)的程序員處理所有可能的錯誤,減少維護(hù)成本传货。
下面使用do-catch來處理可能的異常:
do {
let testResult: String = try testThrow(num: 2)
print(testResult) // Will no print
} catch TestError.errorOne(let num) {
print(num) // 1
} catch TestError.errorTwo(let str) {
print(str) // 2
} catch TestError.errorThree {
print(TestError.errorThree) // errorThree
} catch let err {
print(err) // errorUnknown
}
// 2
rethrows
rethrows
關(guān)鍵字只起到傳遞異常的作用屎鳍,在一個函數(shù)或者方法中,調(diào)用一個會throw的函數(shù)问裕,就可以通過rethrows傳遞可能的異常逮壁,接上面的例子:
func testRethrow(testThrowCall: (Int) throws -> String, num: Int) rethrows -> String {
try testThrowCall(num)
}
觀察函數(shù)申明,其實就是有一個會throw函數(shù)作為參數(shù)粮宛,然后在返回類型前面添加關(guān)鍵字rethrows
窥淆,函數(shù)內(nèi)部直接調(diào)用那個會throw的函數(shù),傳遞可能的異常巍杈,處理rethrows的函數(shù)或方法就和處理throw的函數(shù)或方法一樣:
do {
let testResult: String = try testRethrow(testThrowCall: testThrow, num: 4)
print(testResult) // Will no print
} catch TestError.errorOne(let num) {
print(num) // 1
} catch TestError.errorTwo(let str) {
print(str) // 2
} catch TestError.errorThree {
print(TestError.errorThree) // errorThree
} catch let err {
print(err) // errorUnknown
}
// errorUnknown
總結(jié)
throw在函數(shù)或者方法中拋出異常忧饭,讓調(diào)用者必須明確地處理可能的異常,rethrows本身并不拋出異晨昶瑁或者處理異常词裤,其只起到傳遞異常的作用,最后回到標(biāo)準(zhǔn)庫中的map函數(shù)鳖宾,綜合上述舉個例子:
enum NegativeError: Error {
case negative
}
let nums = [-1, 1, 2, 3, 4]
do {
let strNums = try nums.map { (num) throws -> String in
if num >= 0 {
return String(num)
} else {
throw NegativeError.negative
}
}
print(strNums) // Will no print
} catch let err {
print(err)
}
// negative
這里在map的函數(shù)參數(shù)中使用了throw吼砂,當(dāng)元素小于0時拋出異常