ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

swift 异常处理

2022-05-26 23:33:06  阅读:175  来源: 互联网

标签:vendingMachine 处理 抛出 try vend swift let 异常 VendingMachineError


一、错误类型

1、正常的错误类型通过枚举的方式来定义(通过实现协议Error,但是Error协议进去发现是空的?)

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

这里自定义了3种类型,第三种的insufficientFunds额外增加了参数的设置,用来抛出错误时候额外增加的错误信息

 

二、错误的抛出

1、错误是通过throw关键字抛出,注意throw后面没有s

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

如上所示,抛出了1中的自定义的各个类型;其中VendingMachineError.insufficientFunds 增加了额外的缺多少钱的信息;在实际应用中可以增加更多的参数和其他需要的异常信息

 

2、错误的抛出是通过在函数后面增加throws,如下所示

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

        。。。。。。。
    }

如上标志红色的所示,如果函数中有throw,则需要在函数的列表右括号紧接着throws标志该函数可能会抛出异常(注意这里的throw后面加s)

如果函数要有返回值的话那么要写在throws的后面,比如上面的vend函数要返回String可以如下所示,在throws的后面增加返回String

func vend(itemNamed name: String) throws -> String {
......
}

 

3、闭包的错误抛出跟2的规则差不多是一样的

lazy var blockVend: (_ name: String) throws -> String

如上所示,声明的类型跟普通的函数一样。

 

三、错误的捕获

1、函数可能会抛出异常,那么在执行该函数的时候,前面要增加try

try vendingMachine.vend(itemNamed: snackName)

那么如果有返回值的话

let ret = try vendingMachine.vend(itemNamed: snackName)

注意,此时如果vend函数抛出了异常,则try会继续向外部抛出vend抛出的异常。那么如果不想让vend抛出的异常再向外抛出的话,有两种方法可以阻止

1、在try后面增加问号

    let ret = try? vendingMachine.vend(itemNamed: snackName)
    print(ret)

此时,如果vend抛出异常,则不会再向外抛出异常,ret也有返回值(返回值是nil,因为vend因为异常被抛出了,则正常函数执行的返回代码未执行到所以为空)

2、使用do{}catch的方式

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
    let snackName = favoriteSnacks[person] ?? "Candy Bar"
    let ret = try vendingMachine.vend(itemNamed: snackName)
    print(ret)
}
var vendingMachine = VendingMachine()

do {
    try buyFavoriteSnack(person: "kkqqq", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection {
    print("invalid selection")
} catch VendingMachineError.outOfStock {
    print("out of stock")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
    print("insufficient \(coinsNeeded)")
} catch {
    print("\(error)")
}

如上所示,通过catch捕获各种类型的错误。并在最后的一个catch 不标明任何的类型即捕获任何到达这里的异常,并且error 是异常的类型

如果多个异常的类型要做相同的处理可以把他们合到一起

do {
    try buyFavoriteSnack(person: "kkqqq", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection, VendingMachineError.outOfStock {
    print("invalid selection")
}

如上所示多个异常用逗号隔开

也可以使用条件语句进行判断

catch VendingMachineError.insufficientFunds(let coinsNeeded) where coinsNeeded > 10 {
    print("insufficient \(coinsNeeded)")
}


catch is VendingMachineError {
        print("Couldn't buy that from the vending machine.")
    }

如上列举了两种条件的判断类型,还有其他的条件判断均是可以的

 

3、如果错误不想再继续抛出,并且要在错误抛出的位置直接显示异常

比如上面的例子buyFavoriteSnack函数的列表末尾有throws

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {

这里如果打算让vend如果有异常让程序直接停止不再向外传递,那么throws则不加在buyFavoriteSnack的末尾。但是这样子的话程序编译不通过

这里有个处理方式是在try后面加感叹号!,如下所示

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) {
    let snackName = favoriteSnacks[person] ?? "Candy Bar"
    let ret = try! vendingMachine.vend(itemNamed: snackName)
    print(ret)
}

 

四、类似java中的finally,在本block执行完毕时一定会执行的代码

我们有时会有这么个需求

1、一个函数中有多个return,并且return之前要清理某些资源,如果每个return的地方都写一次的话,那么代码的重复度就会很高

2、当函数中的异常抛出时,有些需要清理的资源还没来得及清理

swift为我们提供了一个关键字defer,当程序在离开本block的时候一定会执行defer中的代码

func processFile(filename: String) throws {
    if exists(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            // Work with the file.
        }
        // close(file) is called here, at the end of the scope.
    }
}

如上的例子来源https://www.cnswift.org/error-handling

在if执行完毕之后会自动执行defer中的close(file)

标签:vendingMachine,处理,抛出,try,vend,swift,let,异常,VendingMachineError
来源: https://www.cnblogs.com/czwlinux/p/16315871.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有