美文网首页
Swift Error Handling(错误处理)

Swift Error Handling(错误处理)

作者: 张科_Zack | 来源:发表于2020-11-26 13:25 被阅读0次

在之前使用 Objective-C 的时候就对异常处理不太搞得明白,使用 swift 已经有一段时间了也是被异常处理经常困扰,因此特意学习了一下swift 中的异常处理,记录一下方便自己翻看。在其它相关语言中使用‘异常处理’这样的字样,但是在swift中很明显看到 Apple 使用 Error Handling,因此我们也使用‘错误处理’的字样来描述这个过程。

错误处理过程

大家经常会遇到在调用系统方法之前需要加一个 try! 关键字,这样经常会被弄的很郁闷。使用 try! 关键字是强行中断错误传递过程,如果在 Apple 的角度其实此时它使用一个 throw 关键字来抛出了一个错误因此 app 开发者需要捕捉这个错误。这里我把错误处理分为两个阶段。第一阶段是函数或者方法构造过程时如果遇到错误需要 throw 错误,第二阶段是函数调用者对错误进行捕捉或者传递。

错误类型

错误抛出之前总要对知道自己抛出的是个什么玩意吧,swift 中抛出的一般是执行 Error 协议的一个枚举。比如

enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}

抛出错误

错误抛出是在我们编写的函数、方法、初始化方法中,尤其需要注意需要在它们返回值之前用 throws 关键字标识该方法(函数、初始化方法)会抛出错误。在函数内部用 throw 关键字抛出。比如

// 1. 商品 Item(价格以及剩余数量)
struct Item {
    var price: Int
    var count: Int
}

// 2. 售货机器
class VendingMachine {
// 3. 商品库存
    var inventory = [
        "Candy Bar": Item(price: 12, count: 7),
        "Chips": Item(price: 10, count: 4),
        "Pretzels": Item(price: 7, count: 11)
    ]
// 4. 投入售货机的硬币数
    var coinsDeposited = 0
// 5. 售货函数(通过商品名称卖出)
    func vend(itemNamed name: String) throws {
        guard let item = inventory[name] else {
// 6.商品名不存在抛出异常
            throw VendingMachineError.invalidSelection
        }

        guard item.count > 0 else {
// 7.商品库存不足抛出异常
            throw VendingMachineError.outOfStock
        }
// 8.投入硬币不足抛出异常
        guard item.price <= coinsDeposited else {
            throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
        }

// 9.购买成功没收与商品等价的硬币数量,哈哈!
        coinsDeposited -= item.price

        var newItem = item
        newItem.count -= 1
// 10.更新该商品库存
        inventory[name] = newItem

        print("Dispensing \(name)")
    }
}

以上代码段描述了错误的抛出,代码段介绍,时间有限不做过多介绍,应该很清晰了。
// 1. 商品 Item(价格以及剩余数量)
// 2. 售货机器
// 3. 商品库存
// 4. 投入售货机的硬币数
// 5. 售货函数(通过商品名称卖出)
// 6.商品名不存在抛出异常
// 7.商品库存不足抛出异常
// 8.投入硬币不足抛出异常
// 9.购买成功没收与商品等价的硬币数量,哈哈!
// 10.更新该商品库存

错误传递(我认为的)

比如在一个 拥有 throws 关键字标识的方法可以直接用 try 接一个可能会抛出错误的方法用来传递错误,比如下边
buyFavoriteSnack() 方法传递了以上 vendingMachine.vend()方法的错误。

let favoriteSnacks = [
    "Alice": "Chips",
    "Bob": "Licorice",
    "Eve": "Pretzels",
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
    let snackName = favoriteSnacks[person] ?? "Candy Bar"
    try vendingMachine.vend(itemNamed: snackName)
}

当然也可以在错误传递的过程中进行错误捕捉但恰巧此时没把所有的错误给捕捉完成错误也是可以继续传递的,比如:

func nourish(with item: String) throws {
    do {
        try vendingMachine.vend(itemNamed: item)
    } catch is VendingMachineError {
        print("Couldn't buy that from the vending machine.")
    }
}

do {
    try nourish(with: "Beet-Flavored Chips")
} catch {
    print("Unexpected non-vending-machine-related error: \(error)")
}

错误捕捉

调用一个会抛出错误的方法时需要使用 try, try?, try! 来标识方法进行错误捕捉。大家经常会头疼什么时候需要使用 try, try?, try!

  1. try!(这样容易被打会抛出运行时错误 crash 程序)
    任何时候都可以使用,这么做会使你的编译器快乐(但你的测试人员,老板,用户可能会感到不快乐。)

  2. try
    常规捕捉错误的处理,需要配合 do { } catch {} 使用, catch 后需要跟上错误类型枚举值,比如

var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
    try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
    print("Success! Yum.")
} 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.")
} catch {
    print("Unexpected error: \(error).")
}

  1. ** try?**(转换错误到可选值)
    抛出错误的方法有返回值时可以使。如果调用方法时抛出错误则返回 nil, 正常返回(没抛出错误时)则返回方法的返回值。比如以下两种情形是等价的,以下代码段 x, y 变量返回值过程是等价的。
func someThrowingFunction() throws -> Int {
    // ...
}

let x = try? someThrowingFunction()

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

当然您也可以方便的进行可选值解包处理过程比如,

func fetchData() -> Data? {
    if let data = try? fetchDataFromDisk() { return data }
    if let data = try? fetchDataFromServer() { return data }
    return nil
}

关闭错误传递

正如 try!可以中断错误传递比如,

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

相关文章

  • 【Swift 3.1】18 - 错误处理 (Error Hand

    【Swift 3.1】18 - 错误处理 (Error Handling) 自从苹果2014年发布Swift,到现...

  • Swift (七)

    错误处理 错误处理(Error handling)是响应错误以及从错误中恢复的过程。Swift 在运行时提供了抛出...

  • Swift - 错误处理

    错误处理 错误处理(Error handling) 是响应错误以及从错误中恢复的过程。Swift 在运行时提供了抛...

  • Swift中的异常处理

    异常处理 错误处理(Error handling)是响应错误以及从错误中恢复的过程 在 Swift 中,错误用符合...

  • Swift5.1—错误处理

    错误处理(Error handling) 是响应错误以及从错误中恢复的过程。Swift 在运行时提供了抛出、捕获、...

  • Swift:错误处理

    中文文档 错误处理(Error handling)是响应错误以及从错误中恢复的过程。Swift 提供了在运行时对可...

  • 18_错误处理

    错误处理(Error handling)是响应错误以及从错误中恢复的过程。Swift 提供了在运行时对可恢复错误的...

  • Swift - 错误处理

    错误处理(Error handling)是响应错误以及从错误中恢复的过程。Swift 提供了在运行时对可恢复错误的...

  • Swift错误处理

    错误处理(Error handling)是响应错误以及从错误中恢复的过程。Swift 提供了在运行时对可恢复错误的...

  • OneDayOneSwift[18] - Error Handl

    错误处理(Error handling)是响应错误以及从错误中恢复的过程。Swift 提供了在运行时对可恢复错误的...

网友评论

      本文标题:Swift Error Handling(错误处理)

      本文链接:https://www.haomeiwen.com/subject/ynpaiktx.html