錯誤分為可恢復的錯誤和不可恢復的錯誤,可恢復的錯誤指的是能預見并處理的錯誤,例如文件不存在,網(wǎng)絡連接失敗等;不可恢復的錯誤指的是一類特殊的bug,例如強制展開值為nil的可空實例,數(shù)組越界訪問等;如果發(fā)生錯誤沒有處理,程序就會停止運行。遺憾的是Swift中似乎只能處理可恢復的錯誤。
斷言
Swift中使用assert添加斷言,第一個參數(shù)表示要檢查的條件,為true時什么也不做,為false時停止運行并顯示錯誤信息;第二個參數(shù)為檢查條件為false時輸出的字符串信息,默認為空;最后兩個參數(shù)為調(diào)用assert所在的源文件名,行號。
/// - Parameters:
/// - condition: The condition to test. `condition` is only evaluated in
/// playgrounds and `-Onone` builds.
/// - message: A string to print if `condition` is evaluated to `false`. The
/// default is an empty string.
/// - file: The file name to print with `message` if the assertion fails. The
/// default is the file where `assert(_:_:file:line:)` is called.
/// - line: The line number to print along with `message` if the assertion
/// fails. The default is the line number where `assert(_:_:file:line:)`
/// is called.
public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)
assert只有在調(diào)試模式才有效,要想在發(fā)布模式也生效可以使用precondition,兩者用法相同
var number1=1
assert(number1 != 1,"number1 is 1")
precondition(number1 != 1,"number1 is 1")
拋出錯誤
遇到錯誤時,可以使用throw拋出一個符合Error協(xié)議的類型的實例,由于Error協(xié)議是一個空協(xié)議,所以不需要任何屬性或方法,就能實現(xiàn)Error協(xié)議。如果該錯誤沒有被處理,則會停止運行,例如下面的代碼。
import Foundation
struct XYError:Error{
}
throw XYError()
捕捉錯誤
Swift中使用do...catch捕捉拋出的錯誤,如果沒有指定錯誤類型則會捕捉所有錯誤
import Foundation
struct XYError:Error{
}
do{
throw XYError()
}catch{
print("error")
}
也可以捕捉多個錯誤
import Foundation
enum NetError:Error{
case serverError
}
struct XYError:Error{
var errorType:Int
}
do{
throw XYError(errorType:3)
throw NetError.serverError
}catch NetError.serverError{
print("net error")
}catch let e as NetError{
print("net error \(e)")
}catch let e as XYError{
print(e.errorType)
}catch{
print("error")
}
可拋出錯誤的函數(shù)
在函數(shù)簽名后面加上throws表示該函數(shù)可能會拋出錯誤,調(diào)用此函數(shù)時前面必須加上try,并且需要把調(diào)用此函數(shù)寫在do...catch內(nèi)。
func makeError(arg:Int) throws->Int{
guard arg > 10 else {
throw XYError(errorType:3)
}
return arg
}
//編譯會報錯
func testFunc(){
try makeError(arg: 1)
}
//正確寫法
func testFunc(){
do{
try makeError(arg: 1)
}catch{
print("error")
}
}
如果調(diào)用可拋出錯誤的函數(shù)的函數(shù)也標記為throws,那么該函數(shù)可以不處理錯誤,錯誤將再次拋出
func makeError(arg:Int) throws->Int{
guard arg > 10 else {
throw XYError(errorType:3)
}
return arg
}
func testFunc() throws{
try makeError(arg: 1)
}
調(diào)用可拋出錯誤的函數(shù)的函數(shù)也可以使用try!告訴編譯器不想處理潛在錯誤,出現(xiàn)錯誤時停止運行
func makeError(arg:Int) throws->Int{
guard arg > 10 else {
throw XYError(errorType:3)
}
return arg
}
func testFunc() {
try! makeError(arg: 1)
}
try還有另外一種變體try?,可以在發(fā)生錯誤時忽略錯誤,但不會停止運行而是返回原本返回值的可空類型
func makeError(arg:Int) throws->Int{
guard arg > 10 else {
throw XYError(errorType:3)
}
return arg
}
func testFunc() {
print(try? makeError(arg: 1))
}