Swift错误处理

来源:互联网 发布:php arrayaccess 编辑:程序博客网 时间:2024/06/05 03:00

Swift错误处理

参考:

  • Magical Error Handling in Swift
  • Play-with-Swift-2/21-Error-Handling

强制退出程序

使用assert,表达式为假,程序强制退出

assert(1>0, "Error")

assert还有一种形式为assertionFailure,程序走到这个函数时,程序会直接终端,并打印中断的信息

assertionFailure("failure")

注意assertassertionFailure都只在开发的过程中起作用,当release程序后,assertassertionFailure就自动失效了。

不过有些时候,希望程序在真正执行起来的时候,在某些情况下,遇到一些严重的错误,程序要强制退出,可以使用preconditionfatalError

precondition(1>0, "Error")fatalError("Error")

Error

在一般的处理过程中可以返回nil表示错误,但是只返回nil,不能表示出错的原因。比如连接网络,如果网络连接不上,就返回一个nil,这样做也是可以的,但是此时只是知道网络没连接上而已。至于是服务端出错还是客户端出错,就不得而知了。所以需要一套完善的错误处理机制。

1.自定义错误类型:

  • 遵守Error协议

如下:

    enum VendingError: Error{        case NoSuchItem        case NotEnoughMoney(Int)        case OutOfStock    }

2.抛出错误,使用throws关键字,抛出错误后,整个函数就已经结束了,所以后面就不用return
真正抛出异常使用throw关键字

    func vend(itemName itemName: String, money: Int) throws -> Int{        guard let item = items[itemName] else{            throw VendingMachine.VendingError.NoSuchItem        }        guard money >= item.price else{            throw VendingMachine.VendingError.NotEnoughMoney(item.price)        }        guard item.count > 0 else{            throw VendingMachine.VendingError.OutOfStock        }        return money - item.price    }   }

此时,这个函数就有两种退出的方式:

1.正确的return
2.抛出异常

错误处理

对于抛出异常的函数,就不能直接调用了,要处理异常。使用try关键字

try!表示坚信函数不会抛出异常,但是这样写也是有风险的。

try! machine.vend(itemName: "Coca Cola", money: pocketMoney)

try?表示如果抛出异常,返回值为nil。所以对于返回值可以使用解包的形式:

if let leftMoney = try? machine.vend(itemName: "Coca Cola", money: pocketMoney){}else{}

如果希望更具错误的类型,来做不同的处理。就需要使用docatch关键字,如下:

do{    pocketMoney = try machine.vend(itemName: "Coca Cola", money: pocketMoney)    print(pocketMoney, "Yuan left")}catch{    print("Error occured during vending")}

要处理不同类型的异常,形式如下:

do{    pocketMoney = try machine.vend(itemName: "Coca Cola", money: pocketMoney)    print(pocketMoney, "Yuan left")}catch VendingMachine.VendingError.NoSuchItem{    print("No Such Item")}catch VendingMachine.VendingError.NotEnoughMoney(let price){    print("No Enough Money", price, "Yuan needed.")}catch VendingMachine.VendingError.OutOfStock{    print("Out of Stock")}catch{    print("Error occured during vending.")}

还有一种形式是:

do{    pocketMoney = try machine.vend(itemName: "Coca Cola", money: pocketMoney)    print(pocketMoney, "Yuan left")}catch let error as VendingMachine.VendingError{}catch{    print("Error occured during vending.")}

defer

在其它语言中,错误处理通常有个finally关键字,不管程序是否抛出异常,finally中的代码都要执行。

swift中引入了defer,它应该写在有可能退出这个函数的语句之前。defer本身的意识是延迟,表示延迟执行。

    func vend(itemName itemName: String, money: Int) throws -> Int{        defer {            print("Hava a nice day")        }        guard let item = items[itemName] else{            throw VendingMachine.VendingError.NoSuchItem        }        ......    }

如果有多个defer,是按倒序来执行的,如下的方法:

    func vend(itemName itemName: String, money: Int) throws -> Int{        defer {            print("Hava a nice day")        }        guard let item = items[itemName] else{            throw VendingMachine.VendingError.NoSuchItem        }        guard money >= item.price else{            throw VendingMachine.VendingError.NotEnoughMoney(item.price)        }        guard item.count > 0 else{            throw VendingMachine.VendingError.OutOfStock        }        defer {            print("Thank you")        }        dispenseItem(itemName: itemName)        return money - item.price    }    private func dispenseItem(itemName: String){        items[itemName]!.count -= 1        print("Enjoy your",itemName)    }

如果调用如下的方法,正常的执行,不会抛出异常:

var pocketMoney = 3try? machine.vend(itemName: "Coca Cola", money: pocketMoney)

则其输出顺序为:

Enjoy your Coca ColaThank youHava a nice day

如果调用如下方法,抛出异常:

var pocketMoney = 2try? machine.vend(itemName: "Coca Cola", money: pocketMoney)

则控制台只会输出:

Hava a nice day

这是因为抛出异常结束程序,只会找抛出异常之前的defer语句