對于大部分現(xiàn)代化面向對象的編程語言都擁有結構化的錯誤處理語法特性,swift也不例外。當我們在一個方法或函數(shù)中實現(xiàn)某些功能時,如果遇到錯誤的用戶輸入則可能導致嚴重的異常問題,此時我們可以選擇通過拋出異常的方式,將此錯誤送給函數(shù)調用者。
我們常用 try-catch 結構,不過在swift編程語言中沒有引入專門的 try 語句塊,而是直接調用之前的 do 語句塊,僅僅將 try 作為拋出異常的函數(shù)或方法的標識,然后在 do 語句塊后接 catch 語句塊捕獲錯誤并進行處理。
do {
let str = try String(contentsOfFile: "/Users/zennychen/Desktop/test.txt", encoding: String.Encoding.ascii)
print("content is: \(str)")
}
catch {
print("file read failed!")
}
第一節(jié) swift中錯誤的表示
在 swift 中如果我們要定義一個表示錯誤的類型非常簡單,只要遵循 Error 協(xié)議就可以了,我們通常用枚舉或結構體來表示錯誤類型,枚舉可能用的多些,因為它能更直觀的表達當前錯誤類型的每種錯誤細節(jié)。
當我們定義了一個錯誤類型之后,可以實現(xiàn) Error 協(xié)議中擴展默認實現(xiàn)的只讀屬性 localizedDescription,用于描述當前錯誤對象的詳細信息
/// 定義一個枚舉類型的錯誤類型
enum MyEnumError: Error {
case errorOne
case errorTwo
/// 實現(xiàn)Error協(xié)議的localizedDescription只讀實例屬性
var localizedDescription: String {
let desc = self == .errorOne ? "the first errror" : "the second error"
return "\(self): \(desc)"
}
}
/// 定義一個結構體類型的錯誤類型
struct MyStructError: Error {
var errCode: Int = 0
/// 實現(xiàn)Error協(xié)議的localizedDescription只讀實例屬性
var localizedDescription: String {
return "The error code is: \(errCode)"
}
}
print("The enum error is: \(MyEnumError.errorOne.localizedDescription)")
print("The struct error is: \(MyStructError().localizedDescription)")
第二節(jié) swift中的錯誤拋出
如果我們在一個函數(shù)或方法中可能要拋出一個錯誤,那么我們必須在該函數(shù)的形參列表后面,返回類型前面(即 -> 前面)添加 throws 關鍵字,以顯示告訴編譯器,該函數(shù)可能會拋出錯誤。
/// 定義一個foo函數(shù),
/// 它可能會拋出一個錯誤,
/// 因此這里用throws限定。
/// 注意throws的位置
func foo(a: Int) throws -> Int {
if a < -10 {
// 如果a的值小于-10,
// 則拋出MyEnumError.errorOne
throw MyEnumError.errorOne
}
else if a > 10 {
// 如果a的值大于10,
// 則拋出MyEnumError.errorTwo
throw MyEnumError.errorTwo
}
else if a == 0 {
// 如果a的值為0,
// 那么拋出MyStructError對象,
// 并且其errCode的值為-1
throw MyStructError(errCode: -1)
}
print("a = \(a)")
return a
}
// ref的類型為:(Int) throws -> Void
let ref = foo(a:)
第三節(jié) 錯誤捕獲與處理
在Swift 編程語言中我們使用 do-catch 塊對錯誤進行捕獲,當我們在調用一個 throws 聲明的函數(shù)或方法時,我們必須把調用語句放在 do 語句塊中,同時 do 語句塊后面緊接著使用 catch 語句塊。
當我們在 do 語句塊中調用了一個可能會拋出錯誤的函數(shù)時,而此時該函數(shù)在執(zhí)行時確實拋出了錯誤,我們在 catch 語句塊匯總可以捕獲錯誤并進行處理,一旦 do 語句塊中拋出錯誤,接下來的代碼將不會被執(zhí)行,會跳到 catch 語句塊中,catch 語句塊中的代碼執(zhí)行完成后,其下面的代碼也會執(zhí)行,如果 do 語句塊中無錯誤拋出,catch 語句塊不會被執(zhí)行。
// 由于在以下語句中包含了對可拋出錯誤的函數(shù)調用,
// 因此這里使用do語句塊將這些調用圍起來
do {
// 對于任一可能會拋出錯誤的函數(shù),
// 在調用前面都必須添加try關鍵字
var value = try foo(a: -100)
value += try foo(a: 100)
value += try foo(a: 0)
print("value = \(value)")
} // 下面緊接著使用catch語句塊
catch let err {
// 如果在do語句塊中有任一錯誤拋出,
// 那么即會執(zhí)行此catch語句塊中的內容
print("err is: \(err)")
}
// 無論上面do語句塊是否有錯誤,
// 這句打印均會執(zhí)行
print("complete")