一.自定义错误类型,使用do catch
处理可能抛出的异常
// 1.枚举必须是遵守Error协议,如果换成类也必须要遵守Error
enum SomeError: Error {
case illegalArg(String)
case outOfBounds(Int, Int)
case outOfMemory
}
// 2.throws 和 throw 注意区别 throws函数的声明
func divide(num1: Int, num2: Int) throws -> Int{
if num2 == 0 {
throw SomeError.illegalArg("0不能作为除数")
}
return num1/num2
}
// 3.调用可能抛出错误的方法,使用do catch处理
func test() {
print(0)
do {
print(1)
let res = try divide(num1: 200, num2: 0)
print(res)
print(2)
} 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(3)
}
注意点:
- 1.方法
divide(num1: 200, num2: 0)
一旦抛出异常,那么之后的打印就不会进行,print(res)和print(2)就都不会进行,就会跳到对应的catch错误中 - 2.do catch一定要写全,类似
switch case
,如果不全编译器会报错Errors thrown from here are not handled because the enclosing catch is not exhaustive
所以,do catch结尾是一定要加,不然就会报错,这个和
switch case
还有点不一样// 这里就是其他类型错误 catch { print("其他错误") }
二.不捕捉Error,在当前函数增加throws声明,Error将自动抛给上层函数,如果最顶层函数(main函数)依然没有捕捉Error,那么程序将终止
func test0() {
// 强制调用,如果出错程序就闪退
try! test1()
// 或者
do {
try test1()
}catch {
}
}
// 如果自己不处理,那么往上抛
func test1() throws{
try test2()
}
// 如果自己不处理,那么往上抛
func test2() throws {
let res = try divide(num1: 200, num2: 0)
print(res)
}
三.使用try? try!调用可能会抛出Error的函数,这样就不用处理Error
func testTry() {
let res1 = try? divide(num1: 20, num2: 10)
print(res1) // Optional(2)
let res2 = try? divide(num1: 20, num2: 0)
print(res2) // nil
let res3 = try! divide(num1: 20, num2: 10)
print(res3) // 2
let res4 = try! divide(num1: 20, num2: 0)
print(res4) // 会闪退
//Fatal error: 'try!' expression unexpectedly raised an error: TEST_Swift.SomeError.illegalArg("0不能作为除数"): file......
}
try!一定要慎用
try? 的本质
var a = try? divide(num1: 20, num2: 10)
// 这两种写法,都是一样的效果
var b: Int?
do {
b = try divide(num1: 20, num2: 10)
} catch { b = nil }
四:rethrows关键字
表示: 函数本身不会抛出错误,单调用闭包参数抛出错误,那么它会将错误向上抛
示例
func exec(_ fn: (Int, Int) throws -> Int, num1: Int, num2: Int) rethrows {
print(try fn(num1,num2))
}
// try? exec(divide, num1: 20, num2: 0)
try! exec(divide, num1: 20, num2: 0)
说白了,rethrows这个关键字告诉我们,这个方法的错误,是由传过来的参数(一般是闭包或者函数)造成的,不是我本身的原因
示例 ??
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T