15-錯誤處理(Error)
錯誤型別
- 開發過程中常見的錯誤
- 語法錯誤(編譯報錯)
- 邏輯錯誤
- 執行時錯誤(可能導致閃退,一般也叫異常)
- …
自定義錯誤
- Swift 中可以通過 Error協議自定義執行時的錯誤資訊
enum SomeError : Error {
case illegalArg(String) case outOfBounds(Int, Int) case outOfMemory
}
- 函式內部通過throw丟擲自定義Error,可能會丟擲Error的函式必須加上throw宣告
func divide(_ num1: Int, _ num2: Int) throws -> Int { if num2 == 0 {
throw SomeError.illegalArg("0不能作為除數") }
return num1 / num2
}
需要使用try呼叫可能會丟擲Error的函式
var result = try divide(20, 10)
do-catch
- 可以使用do-catch捕捉Error
func test() {
print("1")
do {
print("2")
print(try divide(20, 0))
print("3")
} catch let SomeError.illegalArg(msg) {
print("引數異常:", msg)
} catch let SomeError.outOfBounds(size, index) {
print("下標越界:", "size=\(size)", "index=\(index)")
} catch SomeError.outOfMemory {
print("記憶體溢位")
} catch {
print("其他錯誤")
}
print("4")
}
test()
// 1
// 2
// 引數異常: 0不能作為除數 // 4
do{
try dicide(20, 0)
} catch let error {
case let SomeError.illegalArg(msg):
print("引數錯誤", msg)
default:
print("其他錯誤")
}
- 丟擲 Error後, try下一句直到作用域結束的程式碼都將停止執行
處理錯誤
- 處理錯誤的兩種方式
- 通過 do-catch捕捉 Error
- 不捕捉 Error,在當前函式增加 throws 宣告,Error 將自動拋給上層函式
如果最頂層函式(main)依然沒有捕捉 Error,那麼程式將終止
func test() throws {
print("1")
print(try divide(20, 0))
print("2")
}
try test()
// 1
// Fatal error: Error raised at top level
func test() throws {
print("1")
do {
print("2")
print(try divide(20, 0))
print("3")
} catch let error as SomeError {
print(error)
}
print("4")
}
try test()
//1
//2
//illegalArg("0不能作為除數")
//4
try?、try!
- 可以使用 try?、try! 呼叫可能會丟擲 Error 的函式,這樣就不用去處理 Error
func test() {
print("1")
var result1 = try? divide(20, 10) // Optional(2)
var result2 = try? divide(20, 0) // nil
var result3 = try! divide(20, 10) // 2, Int
print("2")
}
test()
- a, b 是等價的
var a = try? divide(20, 0)
var b: Int?
do {
b = try divide(20, 0)
}catch {
b = nil
}
rethrows
- rethrows 表明:函式本身不會丟擲錯誤,但呼叫閉包引數丟擲錯誤,那麼它會將錯誤向上拋
func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, num2: Int) rethrows {
print(try fn(num1, num2))
}
// Fatal error: Error raised at top level
try exec(divide, 20, num2: 0)
defer
- defer語句:用來定義以任何方式(丟擲錯誤,return等)離開程式碼前必須要執行的程式碼
- defer語句將延遲至當前作用域結束之前執行
func open(_ fileName: String) -> Int {
print("open")
return 0
}
func close(_ file: Int) {
print("close")
}
func processFile(_ fileName: String) throws {
let file = open(fileName)
defer {
close(file)
}
// 使用 file
// ...
try divide(20, 0)
// close 將會在這裡呼叫
}
//open
//close
//Fatal error: Error raised at top level
try processFile("text.txt")
- defer 語句的執行順序與定義順序相反
func fn1() { print("fn1")}
func fn2() { print("fn2")}
func test() {
defer {
fn1()
}
defer {
fn2()
}
}
//fn2
//fn1
test()
assert(斷言)
- 很多程式語言都有斷言機制:不符合指定條件就丟擲執行時錯誤,常用於除錯(Debug)階段的條件判斷
- 預設情況下,Swift的斷言只會在 Debug模式下生效,Release模式下會忽略
func divide(_ v1: Int, _ v2: Int) -> Int {
assert(v2 != 0, "除數不能為 0")
return v1 / v2
}
print(divide1(20, 0))
- 增加Swift Flags 修改斷言的預設行為
- assert-config Release: 強制關閉斷言
- assert-config Debug: 強制開啟斷言
fatalError
- 如果遇到嚴重問題,希望結束程式執行時,可以直接使用 fatalError函式丟擲錯誤(這是無法通過 do-catch捕捉的錯誤)
使用了fatalError函式就不需要再寫 return
func test(_ num: Int) -> Int {
if num >= 0 {
return 1
}
fatalError("num 不能小於 0")
}
// num 不能小於 0
test(-1)
- 在某些不得不實現,但不希望別人呼叫的方法,可以考慮內部使用 fatalError函式
class Person {required init(){}}
class Student: Person {
required init(){ fatalError("don't call Student.init")}
init(score: Int){}
}
var stu1 = Student(score: 98)
var stu2 = Student()
區域性作用域
- 可以使用 do 實現區域性作用域
do {
let dog1 = Dog()
dog1.age = 10
dog1.run()
}
do {
let dog2 = Dog()
dog2.age = 10
dog2.run()
}
學習筆記
相關文章
- 錯誤處理:如何通過 error、deferred、panic 等處理錯誤?Error
- Golang 學習——error 錯誤處理淺談GolangError
- 【ERROR】ORA-8103錯誤分析處理Error
- Android - Unparsed aapt error(s)錯誤的處理方法AndroidAPTError
- 錯誤處理
- ORA-00257 archiver error. 錯誤的處理方法HiveError
- PHP 錯誤處理PHP
- php錯誤處理PHP
- Go 錯誤處理Go
- Swift錯誤處理Swift
- Zabbix錯誤處理
- mysqldump錯誤處理MySql
- Go語言(golang)的錯誤(error)處理的推薦方案GolangError
- ORA-00600: internal error code, arguments: [4194] 錯誤處理Error
- PHP錯誤處理和異常處理PHP
- go的錯誤處理Go
- Python錯誤處理Python
- 【問題處理】Error accessing PRODUCT_USER_PROFILE錯誤一例Error
- ORA-00600: internal error code, arguments: [kcratr_scan_lastbwr]錯誤處理ErrorAST
- 異常錯誤資訊處理
- PHP 核心特性 - 錯誤處理PHP
- 常用模組 PHP 錯誤處理PHP
- laravel9 錯誤處理Laravel
- 淺談前端錯誤處理前端
- Oracle異常錯誤處理Oracle
- ORACLE 異常錯誤處理Oracle
- 學習Rust 錯誤處理Rust
- axios 的錯誤處理iOS
- Go語言之錯誤處理Go
- GOLANG錯誤處理最佳方案Golang
- Objective-C:錯誤處理Object
- javascript之處理Ajax錯誤JavaScript
- 搭建dataguard時,錯誤處理
- Oracle錯誤處理思路(一)Oracle
- COM的錯誤處理 (轉)
- 使用PHP錯誤處理 (轉)PHP
- Python錯誤處理和異常處理(二)Python
- 【故障處理】CRS-1153錯誤處理