swift基础day6---错误处理

本文介绍Swift中的错误处理机制,包括如何定义、抛出及捕获错误,以及如何使用do-catch语句来处理错误。还展示了如何将错误转换为可选值和如何禁用错误传递。
错误处理

Swift 在运行时提供了抛出、捕获、传递和操作可恢复错误等支持。Swift 中的错误处理涉及到错误处理模式与Cocoa有关。

表示与抛出错误

遵循Error 协议。

//表示与抛出错误
enum VendingMachineError: Error {
    case invalidSelection   //选择无效
    case insufficientFunds(coinsNeeded: Int)  //金额不足
    case outOfstock    //缺货
}
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
处理错误
1.用 throwing 函数传递错误

一个 throwing 函数可以在其内部抛出错误,并将错误传递到函数被调用时的作用域。
注:只有 throwing 函数可以传递错误。任何在某个非 throwing 函数内部抛出的错误只能在函数内部处理。
throw 语句会立即退出方法.

struct Item {
    var price: Int
    var count: Int
}

class VedingMachine {
    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 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
    }
}

throwing 构造器能像 throwing 函数一样传递错误。例如下面代码中的 PurchasedSnack 构造器在构造过程中调用了 throwing 函数,并且通过传递到它的调用者来处理这些错误。

struct PurchasedSnack {
    let name: String
    init(name: String, vendingMachine:VedingMachine) throws {
        try vendingMachine.vend(itemNamed: name)
        self.name = name
    }
}
2.用 Do-Catch 处理错误

一般形式:

do {
    try expression
    statements
} catch pattern 1 {
    statements
} catch pattern 2 where condition {
    statements
} catch {
    statements
}

能够抛出错误的函数既可以使用 do-catch 语句处理,也可以让调用方来处理错误。如果错误传递到了顶层作用域却依然没有被处理,你会得到一个运行时错误。

3.将错误转换成可选值

try?
对所有的错误使用try?处理:

func fetchData() -> Data? {
    if let data = try? fetchDataFromdisk(){
        return data
    }
    if let data = try? fetchDataFromServer() {
        return data
    }
    return nil
}
4. 禁用错误传递

有时你知道某个 throwing 函数实际上在运行时是不会抛出错误的,在这种情况下,你可以在表达式前面写 try! 来禁用错误传递,这会把调用包装在一个不会有错误抛出的运行时断言中。如果真的抛出了错误,你会得到一个运行时错误。

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
指定清理操作

使用 defer 语句在即将离开当前代码块时执行一系列语句。该语句能执行一些必要的清理工作。可以用 defer 语句来确保文件描述符得以关闭,以及手动分配的内存得以释放。
defer 语句将代码的执行延迟到当前的作用域退出之前。延迟执行的操作会按照它们声明的顺序从后往前执行——也就是说,第一条 defer 语句中的代码最后才执行,第二条 defer 语句中的代码倒数第二个执行,以此类推。最后一条语句会第一个执行。

func processFile(filename: String) throw {
    if exists(filename){
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            //处理文件
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值