swift学习-错误处理(十八)

来源:互联网 发布:数字网络广播系统 编辑:程序博客网 时间:2024/06/07 03:33

错误处理是响应错误以及从错误中返回的过程。swift提供第一类错误支持,包括在运行时抛出,捕获,传送和控制可回收错误。

一些函数和方法不能总保证能够执行所有代码或产生有用的输出。可空类型用来表示值可能为空,但是当函数执行失败的时候,

可空通常可以用来确定执行失败的原因,因此代码可以正确地响应失败。在Swift中,这叫做抛出函数或者抛出方法。


Swift中,错误用符合ErrorType协议的值表示。 Swift枚举特别适合把一系列相关的错误组合在一起,

同时可以把一些相关的值和错误关联在一起。因此编译器会为实现ErrorType协议的Swift枚举类型自动实现相应合成。


//贩卖机错误

enum VendingMachineError:ErrorType {

    //无效的选择

    case InvalidSelection

//    足够的资金

    case InsufficientFunds(coinsNeeded:Int)

    // 无现货

    case OutOfStock

}

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 var item =inventory[name]else {

            throwVendingMachineError.InvalidSelection

            

        }

        guard item.count >0else {

            throwVendingMachineError.OutOfStock

        }

        guard item.price <=coinsDepositedelse {

            throwVendingMachineError.InsufficientFunds(coinsNeeded: item.price -coinsDeposited)


        }

        coinsDeposited -= item.price

        --item.count

        inventory[name] = item

        dispenseSnack(name)

    }

}


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)

}

/*捕捉和处理错误

语法:

do {

     try expression

     statements

} catch pattern1 {

     statements

} catch pattern2 where condition {

      statements

}

*/

var vendingMachine = VendingMachine()

vendingMachine.coinsDeposited =11

do {

    try buyFavoriteSnack("Alice", vendingMachine:vendingMachine)

    print("No Errors throw")

} 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.")

}

//No Errors throw,如果vendingMachine.coinsDeposited这会打印出

//Insufficient funds. Please insert an additional 2 coins.print("No Errors throw")不会执行


/*转换错误为可选值

try?来讲错误处理转化成一个可选值,如果一个错误抛出,那么用了try?的表达值的值为nil


*/

func someThrowingFunction() throws -> Int {

    return 0

}

let x = try?someThrowingFunction()

let y:Int?

do {

    y =trysomeThrowingFunction()

}catch{

    y = nil

}

//如果错误抛出, x,y的值都为nil,注x,y:都为可选类型

/*利用try?来以相同方式处理所有错误

func fetchData() -> Data? {

    if let data = try? fetchDataFromDisk() {return data}

    if let data = try? fetchDataFromServer() {return data}

    return nil

}

*/

/* 禁止错误传播

通过try!来调用抛出函数或方法禁止了错误传送,并且把调用包装在运行时断言,这样就不会抛出错误。

如果错误真的抛出了,会触发运行时错误。


let photo = try! loadImag("./Resources/John Appleseed.jpg")

*/

指定清理操作

使用defer(推迟)语句来在执行一系列的语句。这样不管有没有错误发生,都可以执行一些必要的收尾操作。

包括关闭打开的文件描述符以及释放所有手动分配的内存。

defer语句把执行推迟到退出当前域的时候。defer语句包括defer关键字以及后面要执行的语句。

被推迟的语句可能不包含任何将执行流程转移到外部的代码,比如break或者return语句,或者通过抛出一个错误。

被推迟的操作的执行的顺序和他们定义的顺序相反,也就是说,在第一个defer语句中的代码在第二个defer语句中的代码之后执行。


func processFile(filename: String) throws {

    if exists(filename) {

        let file = open(filename)

        defer {

            close(file)

        }

        while let line = try file.readLine() {

            //work width the file.

        }

        //close(file) is called here, at eht end of the scope.

    }

}

*/

0 0
原创粉丝点击