swift像其他編程語言一樣可以拋出異常并處理異常,本文就詳細(xì)說一下在swift中拋出并處理異常,swift
中的一些簡單異常可以用enum定義,注意這個枚舉要繼承一個空協(xié)議Error,比如下面的代碼:
enum FileReadError : Error {
case FileIsNull
case FileNotFound
}
這里定義了一個異常值的枚舉,接下來我們寫個函數(shù)使用這些異常值,能拋出異常的函數(shù)一定要在函數(shù)后面添加關(guān)鍵字throws,這種函數(shù)一般稱為throwing函數(shù),如果這個函數(shù)有返回值,那么throws要寫在返回值的前面,看下面的例子:
func readFileContent(_ filePath: String) throws -> String {
//1.filePath為空
if filePath == "" {
throw FileReadError.FileIsNull
}
//2.filePath有值,但是沒有對應(yīng)的路徑
if filePath != "/User/Desktop/haha" {
throw FileReadError.FileNotFound
}
//3.取出其中內(nèi)容
return "haha"
}
在swift中有4中方法來處理錯誤:
- 把錯誤傳遞給調(diào)用這個方法的代碼
- 使用
do-catch語句來處理這個錯誤 - 把錯誤處理為一個可選值
- 斷言這個錯誤不會出現(xiàn)
下面將逐一演示
1.使用拋出方法來傳遞錯誤
//拋出錯誤
func throwError(_ filePath: String) throws -> String {
print("錯誤傳遞")
try readFileContent(filePath)
print("未傳遞錯誤")
return "無錯誤"
}
throwError這個函數(shù)并沒有處理函數(shù)readFileContent返回的錯誤,而是將錯誤傳遞給了調(diào)用throwError函數(shù)的地方處理了
2.使用do-catch來捕獲異常并處理
func catchError(_ filePath: String) {
do {
print("捕獲錯誤")
let result = try readFileContent(filePath)
print("未捕獲到錯誤\(result)")
} catch FileReadError.FileIsNull {
print("filePath為空")
} catch FileReadError.FileNotFound {
print("filePath有值,但是沒有對應(yīng)的路徑")
}
}
使用do-catch捕獲異常處理,在do的閉包里執(zhí)行會拋出異常的代碼,在catch分支里匹配異常處理異常
3.把錯誤處理成可選值
代碼示例如下
func buhuoError(_ filePath: String) {
if let result = try? readFileContent(filePath) {
print("可選值非空"+result)
}
}
使用try?將異常轉(zhuǎn)換為可選值,在使用try?的過程中,如果有異常拋出,那么這個語句的值為nil
4.禁用錯誤傳遞
有時候我們知道一個能拋出錯誤的方法在運(yùn)行時間上不會拋出錯誤,在這種情況下,我們可以使用語句try!來禁止錯誤傳遞,并且封裝在斷言內(nèi),如果真的有錯誤拋出,那么程序會崩潰。
實例代碼如下:
func noError(_ filePath: String) {
//如果方法`readFileContent`拋出異常,則程序會崩潰
let result = try! readFileContent(filePath)
}
defer語句
使用defer語句在代碼執(zhí)行離開當(dāng)前代碼塊之前執(zhí)行一些語句。不管代碼執(zhí)行如何離開當(dāng)前代碼塊,不管是因為報錯、return或者break,defer中的語句都能讓我們做一些必要的清理。例如,可以使用defer語句來保證文件描述符被關(guān)閉和手動分配的內(nèi)存被釋放。