Swift4.2语言规范(十九) 错误处理
错误处理是响应程序中的错误条件并从中恢复的过程。Swift为在运行时抛出,捕获,传播和操纵可恢复的错误提供了一流的支持。 某些操作无法保证始终完成执行或产生有用的输出。Optionals用于表示缺少值,但是当操作失败时,了解导致失败的原因通常很有用,这样您的代码就可以做出相应的响应。 例如,考虑从磁盘上的文件读取和处理数据的任务。此任务可能有多种失败方式,包括指定路径中不存在的文件,没有读取权限的文件或未以兼容格式编码的文件。区分这些不同的情况允许程序解决一些错误并向用户传达它无法解决的任何错误。 注意 Swift中的错误处理与使用 抛出错误在Swift中,错误由符合 Swift枚举特别适合于对一组相关错误条件进行建模,其中相关值允许有关要传达的错误性质的附加信息。例如,以下是您如何表示在游戏中操作自动售货机的错误条件: 1 enum VendingMachineError: Error { 2 case invalidSelection 3 case insufficientFunds(coinsNeeded: Int) 4 case outOfStock 5 } 抛出错误可以指示发生了意外情况,并且正常的执行流程无法继续。您使用 throw VendingMachineError.insufficientFunds(coinsNeeded: 5) 处理错误当抛出错误时,一些周围的代码必须负责处理错误 - 例如,通过纠正问题,尝试替代方法或通知用户失败。 有四种方法可以处理Swift中的错误。您可以将错误从函数传播到调用该函数的代码,使用 当函数抛出错误时,它会改变程序的流程,因此您可以快速识别代码中可能引发错误的位置,这一点很重要。要在代码中标识这些位置,请在调用可能引发错误的函数,方法或初始值设定项的代码之前编写 注意 在Swift的错误处理类似的异常处理在其他语言中,使用了的 使用Throw函数传播错误要指示函数,方法或初始值设定项可以抛出错误,请 1 func canThrowErrors() throws -> String 2 3 func cannotThrowErrors() -> String 抛出函数将在其中抛出的错误传播到调用它的范围。 注意 只有抛出函数才能传播错误。必须在函数内部处理在非throwing函数内抛出的任何错误。 在下面的示例中, 1 struct Item { 2 var price: Int 3 var count: Int 4 } 5 6 class VendingMachine { 7 var inventory = [ 8 "Candy Bar": Item(price: 12,count: 7), 9 "Chips": Item(price: 10,count: 4),10 "Pretzels": Item(price: 7,count: 11) 11 ] 12 var coinsDeposited = 0 13 14 func vend(itemNamed name: String) throws { 15 guard let item = inventory[name] else { 16 throw VendingMachineError.invalidSelection 17 } 18 19 guard item.count > 0 else { 20 throw VendingMachineError.outOfStock 21 } 22 23 guard item.price <= coinsDeposited else { 24 throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited) 25 } 26 27 coinsDeposited -= item.price 28 29 var newItem = item 30 newItem.count -= 1 31 inventory[name] = newItem 32 33 print("Dispensing (name)") 34 } 35 } 该 因为该 1 let favoriteSnacks = [ 2 "Alice": "Chips",3 "Bob": "Licorice",4 "Eve": "Pretzels",5 ] 6 func buyFavoriteSnack(person: String,vendingMachine: VendingMachine) throws { 7 let snackName = favoriteSnacks[person] ?? "Candy Bar" 8 try vendingMachine.vend(itemNamed: snackName) 9 } 在这个例子中,该函数查找给定人最喜欢的零食,并尝试通过调用该方法为他们购买。因为该方法可以抛出错误,所以使用前面的关键字调用它。 抛出初始化器可以像抛出函数一样传播错误。例如, 1 struct PurchasedSnack { 2 let name: String 3 init(name: String,vendingMachine: VendingMachine) throws { 4 try vendingMachine.vend(itemNamed: name) 5 self.name = name 6 } 7 } 使用Do-Catch处理错误您使用 以下是 1 do { 2 try expression 3 statements 4 } catch pattern 1 { 5 statements 6 } catch pattern 2 where condition { 7 statements 8 } catch { 9 statements 10 } 您之后编写一个模式 例如,以下代码匹配 1 var vendingMachine = VendingMachine() 2 vendingMachine.coinsDeposited = 8 3 do { 4 try buyFavoriteSnack(person: "Alice",vendingMachine: vendingMachine) 5 print("Success! Yum.") 6 } catch VendingMachineError.invalidSelection { 7 print("Invalid Selection.") 8 } catch VendingMachineError.outOfStock { 9 print("Out of Stock.") 10 } catch VendingMachineError.insufficientFunds(let coinsNeeded) { 11 print("Insufficient funds. Please insert an additional (coinsNeeded) coins.") 12 } catch { 13 print("Unexpected error: (error).") 14 } 15 // Prints "Insufficient funds. Please insert an additional 2 coins." 在上面的示例中, 这些 例如,可以编写上面的示例,以便 1 func nourish(with item: String) throws { 2 do { 3 try vendingMachine.vend(itemNamed: item) 4 } catch is VendingMachineError { 5 print("Invalid selection,out of stock,or not enough money.") 6 } 7 } 8 9 do { 10 try nourish(with: "Beet-Flavored Chips") 11 } catch { 12 print("Unexpected non-vending-machine-related error: (error)") 13 } 14 // Prints "Invalid selection,or not enough money." 在 将错误转换为可选值您可以 1 func someThrowingFunction() throws -> Int { 2 // ... 3 } 4 5 let x = try? someThrowingFunction() 6 7 let y: Int? 8 do { 9 y = try someThrowingFunction() 10 } catch { 11 y = nil 12 } 如果 使用时, 1 func fetchData() -> Data? { 2 if let data = try? fetchDataFromDisk() { return data } 3 if let data = try? fetchDataFromServer() { return data } 4 return nil 5 } 禁用错误传播有时你知道抛出函数或方法实际上不会在运行时抛出错误。在这些情况下,您可以 例如,以下代码使用一个 let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg") 指定清理操作
一 1 func processFile(filename: String) throws { 2 if exists(filename) { 3 let file = open(filename) 4 defer { 5 close(file) 6 } 7 while let line = try file.readline() { 8 // Work with the file. 9 } 10 // close(file) is called here,at the end of the scope. 11 } 12 } 上面的示例使用一个 注意
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |