Swift基础语法(十)Error
2022-05-15 本文已影响0人
iOS之文一
开发中会遇到编时错误、逻辑错误、运行时错误,有的错误只能在运行时爆出来,这种影响较大,且不易察觉,需要专门处理,Swift可以通过Error协议定义运行时的错误信息
主要内容:
- 异常抛出
- 异常处理
- defer
- 断言
- fatalError
1. 异常抛出
代码:
/*
1、抛出异常
*/
enum SomeError : Error {
case illegalArg(String)
case outOfBounds(Int, Int)
case outOfMemory
}
func divide(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw SomeError.illegalArg("0不能作为除数")
}
return num1 / num2
}
var result = try divide(20,10)
说明:
1、抛出错误的函数,必须使用关键字throws
2、使用throw进行抛出
3、抛出的异常必须遵守Error协议,枚举、结构体、类都可以作为Error,因为只要遵守Error协议就可以
4、抛出异常后必须自己处理一下,而不能让系统处理,这样会闪退(我这里并没有处理,下面会讲)
5、可能抛出异常的函数需要使用try调用,可以避免编译报错
2. 异常处理
2.1 do-catch捕获
使用do-catch捕获异常,并处理
代码:
/*
2、do- catch
*/
func test() {
print("1")
do {
print("2")
print(try divide(20, 0))
print("3")
} catch let SomeError.illegalArg(msg) {
print("参数异常:", msg)
} catch let SomeError.outOfBounds(size, index) { print("下标越界:", "size=\(size)", "index=\(index)")
} catch SomeError.outOfMemory {
print("内存溢出")
} catch {
print("其他错误")
}
print("4")
}
/*
1
2
参数异常: 0不能作为除数
4
*/
//test()
说明:
1、do中写可能会出现异常的代码
2、catch中写对抛出的异常的处理
3、do中的divide如果出现异常,后边的print("3")就不会执行了
4、但是继续会执行catch,以及print("4")
2.2 throws抛出异常给上层函数
代码:
/*
3、throws抛出异常
*/
func test2() throws {
do {
print(try divide(200, 0))
} catch is SomeError {
print("Thisis SomeError")
}
}
func test1() throws {
try test2()
}
func test0() throws {
try test1()
}
// Thisis SomeError
try test0()
说明:
1、自己不处理,可以向上抛出异常,让上一层函数进行处理
2、一直抛到main函数让系统执行
2.3 rethrows抛出闭包参数异常给上层函数
代码:
/*
4、rethorows
*/
func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows {
print(try fn(num1, num2))
}
// Fatal error: Error raised at top level
try exec(divide, 20, 0)
说明:
- 函数本身不会抛出错误,但是调用闭包参数时会抛出错误,可以使用rethrows
- 此时也是将错误向上抛
- 并且这个时候其实也是可以使用throws,只不过使用rethrows更准确
2.4 Error的不处理方式
代码:
/*
5、Error不处理方式
*/
func test3() {
print("1")
var result1 = try? divide(20, 10)
var result2 = try? divide(20, 0)
var result3 = try! divide(20, 10)
print("2")
}
test3()
说明:
- 使用try?/try!调用可能会抛出Error的函数,不需要去处理Error
- 如果出现异常,会返回nil
- try!就是自动解包
3. defer
代码:
/*
6、defer
*/
func fn1() {
print("fn1")
}
func fn2() {
print("fn2")
}
func test4() {
defer {
fn1()
}
defer {
fn2()
}
}
test4()
说明:
1、不论defer语句放在函数体的什么地方,他都会延迟到当前作用域结束之前执行
2、不论是什么方式离开的代码块,正常离开或者是抛出异常离开都是必须要执行的
3、defer语句的执行顺序与定义顺序相反
4. 断言
不符合指定条件就抛出运行时错误,常用于调试(Debug)阶段的条件判断,默认情况下,Swift的断言只会在Debug模式下生效,Release模式下会忽略
代码:
/*
7、断言
*/
func divide2(_ v1: Int, _ v2: Int) -> Int { assert(v2 != 0, "除数不能为0")
return v1 / v2
}
print(divide2(20, 0))
修改默认断言:
说明:
- -assert-config Release:强制关闭断言
- -assert-config Debug:强制开启断言
5. fatalError
如果遇到严重问题,希望结束程序运行时,可以直接使用fatalError函数抛出错误(这是无法通过do-catch捕捉的错误)
代码:
/*
8、fatalError
*/
func test(_ num: Int) -> Int {
if num >= 0 {
return 1
}
fatalError("num不能小于0")
}
注意:
- 此时不需要再写return