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
- 【ERROR】ORA-8103錯誤分析處理Error
- Golang 學習——error 錯誤處理淺談GolangError
- Camunda 流程執行錯誤處理ERROR BOUNDARY EVENTError
- 錯誤處理
- Python錯誤處理Python
- PHP 錯誤處理PHP
- php錯誤處理PHP
- Go 錯誤處理Go
- Go語言(golang)的錯誤(error)處理的推薦方案GolangError
- 【譯】 WebSocket 協議第八章——錯誤處理(Error Handling)Web協議Error
- openGauss 處理錯誤表
- go的錯誤處理Go
- axios 的錯誤處理iOS
- Python錯誤處理和異常處理(二)Python
- Oracle異常錯誤處理Oracle
- 淺談前端錯誤處理前端
- ORACLE 異常錯誤處理Oracle
- PHP 核心特性 - 錯誤處理PHP
- Go語言之錯誤處理Go
- grpc中的錯誤處理RPC
- laravel9 錯誤處理Laravel
- 學習Rust 錯誤處理Rust
- Go 函式多返回值錯誤處理與error 型別介紹Go函式Error型別
- rust學習十、異常處理(錯誤處理)Rust
- node端統一錯誤處理
- node錯誤處理與日誌
- [轉] Scala Try 與錯誤處理
- js錯誤處理權威指北JS
- [譯] 使用 Catcher 處理 Flutter 錯誤Flutter
- 如何處理錯誤訊息PleaseinstalltheLinuxkernelheaderfilesLinuxHeader
- 錯誤碼全域性處理(二)
- 錯誤碼全域性處理(一)
- PHP安裝後錯誤處理PHP
- 常用模組 PHP 錯誤處理PHP
- Restful API 中的錯誤處理RESTAPI
- 請教 Element 的錯誤處理
- 異常錯誤資訊處理