Swift基礎(chǔ)-14(錯誤處理)

1.表示并拋出錯誤

在 Swift 中,錯誤用符合Error協(xié)議的類型的值來表示。這個空協(xié)議表明該類型可以用于錯誤處理。
Swift 的枚舉類型尤為適合構(gòu)建一組相關(guān)的錯誤狀態(tài),枚舉的關(guān)聯(lián)值還可以提供錯誤狀態(tài)的額外信息。

enum VendingMachineError : Error {
    case invalidSelection                    //選擇無效
    case insufficientFunds(coinsNeeded: Int) //金額不足
    case outOfStock                          //缺貨
}
2.處理錯誤

某個錯誤被拋出時,附近的某部分代碼必須負(fù)責(zé)處理這個錯誤,例如糾正這個問題、嘗試另外一種方式、或是向用戶報(bào)告錯誤。
Swift 中有4種處理錯誤的方式。你可以把函數(shù)拋出的錯誤傳遞給調(diào)用此函數(shù)的代碼、用do-catch語句處理錯誤、將錯誤作為可選類型處理、或者斷言此錯誤根本不會發(fā)生。

注意
Swift 中的錯誤處理和其他語言中用try,catch和throw進(jìn)行異常處理很像。和其他語言中(包括 Objective-C )的異常處理不同的是,Swift 中的錯誤處理并不涉及解除調(diào)用棧,這是一個計(jì)算代價(jià)高昂的過程。就此而言,throw語句的性能特性是可以和return語句相媲美的。

  • 用 throwing 函數(shù)傳遞錯誤
    為了表示一個函數(shù)、方法或構(gòu)造器可以拋出錯誤,在函數(shù)聲明的參數(shù)列表之后加上throws關(guān)鍵字。一個標(biāo)有throws關(guān)鍵字的函數(shù)被稱作throwing 函數(shù)。如果這個函數(shù)指明了返回值類型,throws關(guān)鍵詞需要寫在箭頭(->)的前面。
func canThrowErrors() throws -> String
func cannotThrowErrors() -> String

注意
只有 throwing 函數(shù)可以傳遞錯誤。任何在某個非 throwing 函數(shù)內(nèi)部拋出的錯誤只能在函數(shù)內(nèi)部處理。”

struct Item {
  var price: Int
  var count: Int
}
class VendingMachine {
  var inventory = [
      "Candy Bar": Item(price: 12, count: 7),
      "Chips": Item(price: 10, count: 4),
      "Pretzels": Item(price: 7, count: 11)
  ]
  var coinsDeposited = 0
  func dispenseSnack(snack: String) {
      print("Dispensing \(snack)")
  }
  func vend(itemNamed name: String) throws {
      guard let item = inventory[name] else {
          throw VendingMachineError.InvalidSelection
      }
      guard item.count > 0 else {
          throw VendingMachineError.OutOfStock
      }
      guard item.price <= coinsDeposited else {
          throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited)
      }
      coinsDeposited -= item.price
      var newItem = item
      newItem.count -= 1
      inventory[name] = newItem
      print("Dispensing \(name)")
  }
}

在vend(itemNamed:)方法的實(shí)現(xiàn)中使用了guard語句來提前退出方法,確保在購買某個物品所需的條件中,有任一條件不滿足時,能提前退出方法并拋出相應(yīng)的錯誤。由于throw語句會立即退出方法,所以物品只有在所有條件都滿足時才會被售出。

  • 用 Do-Catch 處理錯誤
    可以使用一個do-catch語句運(yùn)行一段閉包代碼來處理錯誤。如果在do子句中的代碼拋出了一個錯誤,這個錯誤會與catch子句做匹配,從而決定哪條子句能處理它。
do {
    try expression
    statements
} catch pattern 1 {
    statements
} catch pattern 2 where condition {
    statements
}

使用姿勢如下:

var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
    try buyFavoriteSnack("Alice", vendingMachine: vendingMachine)
} catch VendingMachineError.InvalidSelection {
    print("Invalid Selection.")
} catch VendingMachineError.OutOfStock {
    print("Out of Stock.")
} catch VendingMachineError.InsufficientFunds(let coinsNeeded) {
    print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
}
// 打印 “Insufficient funds. Please insert an additional 2 coins.”

buyFavoriteSnack(person:vendingMachine:)函數(shù)在一個try表達(dá)式中調(diào)用,因?yàn)樗軖伋鲥e誤。如果錯誤被拋出,相應(yīng)的執(zhí)行會馬上轉(zhuǎn)移到catch子句中,并判斷這個錯誤是否要被繼續(xù)傳遞下去。如果沒有錯誤拋出,do子句中余下的語句就會被執(zhí)行。”

  • 將錯誤轉(zhuǎn)換成可選值
    可以使用try?通過將錯誤轉(zhuǎn)換成一個可選值來處理錯誤。如果在評估try?表達(dá)式時一個錯誤被拋出,那么表達(dá)式的值就是nil。例如,在下面的代碼中,x和y有著相同的數(shù)值和等價(jià)的含義:
func someThrowingFunction() throws -> Int {
}

let x = try? someThrowingFunction()
let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

如果someThrowingFunction()拋出一個錯誤,x和y的值是nil。否則x和y的值就是該函數(shù)的返回值。注意,無論someThrowingFunction()的返回值類型是什么類型,xy都是這個類型的可選類型。例子中此函數(shù)返回一個整型,所以x和y是可選整型。

  • defer關(guān)鍵字
    defer關(guān)鍵字用來處理類似Ojective C中@try-@catch-@finally中,@finally的作用。
    比如,我們打開文件,如果拋出錯誤的話,我們總希望關(guān)閉這個文件句柄。
func contents(of filePath:String) throws -> String{
    let file = open(filePath,O_RDWR)
    defer {
        close(file)
    }
    //...
}

關(guān)于defer,有兩點(diǎn)需要注意
多個defer會按照逆序的方式執(zhí)行。
當(dāng)你的程序遇到嚴(yán)重錯誤,比如fatalError,或者強(qiáng)制解析nil,或者segfaults的時候,defer的代碼塊并不會執(zhí)行。

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

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

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