定义一个方法,获取两个数的除数,针对下面这段代码来进行Error的处理
func divide(_ num1: Int, _ num2: Int) -> Int {
num1 / num2
}
当 num2 为 0 的时候,上面代码会发生运行时错误,导致程序崩溃
为解决这个问题,我们需要在代码中对 num2 == 0 单独做判断,然后抛出异常信息
struct MyError: Error {
var msg: String
}
func divide(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw MyError.init(msg: "除数不能为0")
}
return num1 / num2
}
这样当调用 divide 这个方法的时候需要对有可能捕获到的异常信息进行处理,处理方式如下
1、通过 do-catch 捕捉 Error
do {
print(1)
print(try divide(10, 0))
print(2)
} catch let error as MyError {
print(3)
print(error.msg)
} catch {
print("其它错误")
}
// 打印结果
1
3
除数不能为0
do catch 必须对所有可能出现的错误结果进行罗列,不然会报错,所以在上面会有 catch 打印"其他错误", 如果不想对详细错误信息进行处理,也可以直接这样写
do {
print(try divide(10, 0))
} catch {
print("参数错误")
// 在catch的作用域中自带一个error,可以直接打印
print(error)
}
2、不捕捉Error,在当前函数增加throws声明,Error将自动抛给上层函数,如果最顶层函数(main函数)依然没有捕捉Error,那么程序将终止
func test() throws {
print(try divide(10, 0))
}
3、可以使用 try? try! 调用可能会抛出Error的函数,这样就不用去处理Error
print(try? divide(10, 1))
print(try? divide(10, 0))
print(try! divide(10, 2))
print(try! divide(10, 0))
// 打印结果
Optional(10)
nil
5
崩溃
需要注意一下,使用try?得到的结果是可选类型
使用try!解包可能会导致崩溃,除非你确定除数不是0,否则不要用
4、assert(断言)
断言机制:不符合指定条件就抛出运行时错误,常用于调试(debug)阶段的条件判断
func divide(_ v1: Int, _ v2: Int) -> Int {
// 当条件为 false时,打印断言中的抛出的错误信息
assert(v2 != 0, "除数不能为0")
return v1 / v2
}
默认情况下,Swift的断言只会在Debug模式下生效,Release模式下会忽略。可手动强制开启或者关闭,TARGETS---Building Settings---Other Swift Flags
- -assert-config Release:Debug模式下强制关闭断言
-
-assert-config Debug:Release模式下强制开启断言
assert@2x.png
5、fatalError
如果遇到严重问题,希望结束程序运行,可以直接使用fatalError函数抛出错误。
注:使用了fatalError函数,就不需要再写return
func divide(_ v1: Int, _ v2: Int) -> Int {
if v2 != 0 {
return v1 / v2
}
fatalError("除数不能为0")
}
6、defer
defer语句:用来定义以任何方式(抛错误、return等)离开代码块前必须要执行的代码,也就是说defer语句将延迟至当前作用域结束之前执行
func open(_ filename: String) -> Int {
print("open")
return 0
}
func close(_ file: Int) {
print("close")
}
func processFile(_ filename: String) throws {
let file = open(filename)
defer {
close(file)
}
// 程序执行到这里会停止,停止之前会调用 defer 中的 close方法
print(try divide(20, 0))
// close将会在这里调用
}