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