15-錯誤處理

錯誤類型

  • 開發(fā)過程常見的錯誤

□ 語法錯誤(編譯報錯)

□ 邏輯錯誤

□ 運行時錯誤(可能會導(dǎo)致閃退,一般也叫做異常)

□ ......

自定義錯誤

  • Swift中可以通過Error協(xié)議自定義運行時的錯誤信息
enum SomeError : Error {
   case illegalArg(String) 
   case outOfBounds(Int, Int) 
   case outOfMemory                                                
} 
  • 函數(shù)內(nèi)部通過throw拋出自定義Error,可能會拋出Error的函數(shù)必須加上throws聲明
func divide(_ num1: Int, _ num2: Int) throws -> Int { 
    if num2 == 0 {                                     
        throw SomeError.illegalArg("0不能作為除數(shù)") 
    } 
    return num1 / num2
}
  • 需要使用try調(diào)用可能會拋出Error的函數(shù)
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("參數(shù)異常:", msg)                                                              
  } catch let SomeError.outOfBounds(size, index) {                                                              
    print("下標越界:", "size=\(size)", "index=\(index)")                                                              
  } catch SomeError.outOfMemory {                                
    print("內(nèi)存溢出") 
  } catch {                                                              
    print("其他錯誤") 
  }                                                                
  print("4") 
} 
test()
 // 1
 // 2
 // 參數(shù)異常: 0不能作為除數(shù) // 4 
  • 拋出Error后,try下一句直到作用域結(jié)束的代碼都將停止運行

處理Error

  • 處理Error的2種方式

① 通過do-catch捕捉Error
② 不捕捉Error,在當前函數(shù)增加throws聲明,Error將自動拋給上層函數(shù)

?? 如果最頂層函數(shù)(main函數(shù))依然沒有捕捉Error,那么程序?qū)⒔K止

func test() throws {
  print("1")
  print(try divide(20, 0))                                           
  print("2") 
} 

try test()
 // 1
 // Fatal error: Error raised at top level 
do {
  print(try divide(20, 0))
} catch is SomeError {
  print("SomeError")                                                
} 
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不能作為除數(shù)") // 4 

try?、try!

  • 可以使用try?、try!調(diào)用可能會拋出Error的函數(shù),這樣就不用去處理Error
func test() {
      print("1")
      var result1 = try? divide(20, 10) // Optional(2), Int?
      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表明:函數(shù)本身不會拋出錯誤,但調(diào)用閉包參數(shù)拋出錯誤,那么它會將錯誤向上拋
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, 0)

defer

  • defer語句:用來定義以任何方式(拋錯誤、return等)離開代碼塊前必須要執(zhí)行的代碼

  • defer語句將延遲至當前作用域結(jié)束之前執(zhí)行

func open(_ filename: String) -> Int { 
    print("open")                                              
    return 0 
} 

func close(_ file: Int) {
    print("close")                                                 
} 
  • defer語句的執(zhí)行順序與定義順序相反
func fn1() { print("fn1") }
func fn2() { print("fn2") }
func test() {
   defer { fn1() }
   defer { fn2() }
}
test()
// fn2
// fn1
func processFile(_ filename: String) throws { 
    let file = open(filename)
    defer { 
        close(file)
    }                                             
     // 使用file
     // ....
     try divide(20, 0) 

    // close將會在這里調(diào)用 
} 

try processFile("test.txt")
// open
// close
// Fatal error: Error raised at top level 

assert(斷言)

  • 很多編程語言都有斷言機制:不符合指定條件就拋出運行時錯誤,常用于調(diào)試(Debug)階段的條件判斷

  • 默認情況下,Swift的斷言只會在Debug模式下生效,Release模式下會忽略

func divide(_ v1: Int, _ v2: Int) -> Int {
 assert(v2 != 0, "除數(shù)不能為0")
 return v1 / v2 
}
print(divide(20, 0))
  • 增加Swift Flags修改斷言的默認行為

□ -assert-config Release:強制關(guān)閉斷言

□ -assert-config Debug:強制開啟斷言

image.png

fatalError

  • 如果遇到嚴重問題,希望結(jié)束程序運行時,可以直接使用fatalError函數(shù)拋出錯誤(這是無法通過do-catch捕捉的錯誤)

使用了fatalError函數(shù),就不需要再寫return

func test(_ num: Int) -> Int {
   if num >= 0 {                                    
      return 1 
    }                                              
   fatalError("num不能小于0") 
} 
  • 在某些不得不實現(xiàn)、但不希望別人調(diào)用的方法,可以考慮內(nèi)部使用fatalError函數(shù)
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 實現(xiàn)局部作用域
do {
    let dog1 = Dog()                                              
    dog1.age = 10                                                  
    dog1.run() 
} 

do {
    let dog2 = Dog()                                        
    dog2.age = 10                                                  
    dog2.run() 
} 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 錯誤處理也就是異常處理 錯誤類型 開發(fā)過程常見的錯誤 語法錯誤(編譯報錯) 邏輯錯誤 運行時錯誤(可能會導(dǎo)致閃退,...
    codeTao閱讀 150評論 0 1
  • 一、錯誤處理 1.1、錯誤類型語法錯誤(編譯報錯)邏輯錯誤運行時錯誤(可能會導(dǎo)致閃退,一般也叫做異常) 1.2、自...
    IIronMan閱讀 695評論 0 3
  • 1.Swift中的錯誤處理方式 Swift中錯誤用符合Error協(xié)議的類型表示。一般是枚舉enum或者結(jié)構(gòu)體str...
    coder_zhengyi閱讀 1,285評論 0 1
  • 1.自定義錯誤 自定義運行時的錯誤信息 2.do-catch 3.處理Error 處理Error的2中方式:1.通...
    一抹相思淚成雨閱讀 336評論 0 2
  • 錯誤的類型 開發(fā)過程中常見的錯誤:語法錯誤(編譯報錯)邏輯錯誤(一般跟業(yè)務(wù)相關(guān))運行時錯誤(可能會導(dǎo)致閃退,一般也...
    Jax_YD閱讀 917評論 0 3

友情鏈接更多精彩內(nèi)容