Swift

Swift基础语法(十)Error

2022-05-15  本文已影响0人  iOS之文一

Swift基础学习文章汇总

开发中会遇到编时错误、逻辑错误、运行时错误,有的错误只能在运行时爆出来,这种影响较大,且不易察觉,需要专门处理,Swift可以通过Error协议定义运行时的错误信息

主要内容:

  1. 异常抛出
  2. 异常处理
  3. defer
  4. 断言
  5. 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)

说明:

  1. 函数本身不会抛出错误,但是调用闭包参数时会抛出错误,可以使用rethrows
  2. 此时也是将错误向上抛
  3. 并且这个时候其实也是可以使用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()

说明:

  1. 使用try?/try!调用可能会抛出Error的函数,不需要去处理Error
  2. 如果出现异常,会返回nil
  3. 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))

修改默认断言:

修改默认断言.png

说明:

  1. -assert-config Release:强制关闭断言
  2. -assert-config Debug:强制开启断言

5. fatalError

如果遇到严重问题,希望结束程序运行时,可以直接使用fatalError函数抛出错误(这是无法通过do-catch捕捉的错误)
代码:

/*
 8、fatalError
 */
func test(_ num: Int) -> Int {
    if num >= 0 {
        return 1
    }
    fatalError("num不能小于0")
}

注意:

上一篇下一篇

猜你喜欢

热点阅读