Swift 异常处理

Posted iLife~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift 异常处理相关的知识,希望对你有一定的参考价值。

Swift 异常处理

错误类型

  • 语法错误
  • 逻辑错误
  • 运行时错误

自定义错误

通过error 协议来自定义错误,通常我们使用枚举类型来定义错误

enum SomeError :Error {
    //关联类型是符串
    case illegalArg(String)
    case outOfBounds(Int,Int)
    case outOfMemory
}

调用可能会抛出异常的函数的时候需要使用try关键字,do...catch 来捕捉错误,如果不处理,Error 将抛给上层函数,到了顶层系统也没处理,则系统会闪退处理

//如果方法要抛出异常,则需要throw关键字
func divide(_ num:Int,_ num2:Int)throws -> Int {
    if 0 == num2 {
        throw SomeError.illegalArg("除数不能为0")
    }
   return num/num2
}
Fatal error: Error raised at top level: Swift_Study.SomeError.illegalArg("除数不能为0"): file Swift/ErrorType.swift, line 200
2021-05-11 16:02:10.028783+0800 Swift_Study[60673:713389] Fatal error: Error raised at top level: Swift_Study.SomeError.illegalArg("除数不能为0"): file Swift/ErrorType.swift, line 200
(lldb) 

捕捉异常处理

do{
    print(try divide(10,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("其他错误")
}

在此,我们定义了另一种error类型

enum MyError :Error {
    //关联类型是字符串
    case illegalArg(String)
    case outOfBounds(Int,Int)
    case outOfMemory
}

抛出这种类型的异常,然后用SomeError类型去接收和捕捉处理会怎么样

func divide(_ num:Int,_ num2:Int)throws -> Int {
    if 0 == num2 {
        throw MyError.illegalArg("除数不能为0")
    }
   return num/num2
}

//转换异常为SomeError类型,然后处理
do{
    print(try divide(10,0))
}catch let error as SomeError{
    print(error)
}

//只要是SomeError,就捕捉处理
do{
    print(try divide(10, 0))
}catch is SomeError{
    print(SomeError.illegalArg("cuowu"))
}


结果是,并不能捕捉到异常,系统会闪退处理

Fatal error: Error raised at top level: Swift_Study.MyError.illegalArg("除数不能为0"): file Swift/ErrorType.swift, line 200
2021-05-11 16:23:57.553676+0800 Swift_Study[61457:730733] Fatal error: Error raised at top level: Swift_Study.MyError.illegalArg("除数不能为0"): file Swift/ErrorType.swift, line 200
(lldb) 

如果抛出的还是SomeError类型的错误,怎转换是没有问题的

illegalArg("除数不能为0")
illegalArg("cuowu")
Program ended with exit code: 0

try? try!

如果只是想调用下这个抛出异常的函数,不想去处理错误,也就是不想用do...catch来捕捉,怎么可以?->用try? try! 来调用

如果调用成功,函数的返回结果会被包装成可选类型

如果函数抛出了错误,怎返回值为nil

//a b 效果是等价的var a = try? divide(20, 0)var b :Int?do{    b = try divide(20, 0)}catch{    b = nil }

rethrows

Rethorws 表明,函数本身不会抛出错误,但是闭包参数可能会抛出错误,那么它会将错误向上抛。

比如

func exec (_ fn:(Int,Int) throws ->Int,num1:Int ,num2:Int) rethrows{  print(try fn(num1,num2))}

这个函数有三个参数,第一个参数是一个可能抛出异常的函数fn,也可能是个闭包表达式,这个函数本身不会抛出异常,但是他的参数可能会抛出异常,所以

此处用rethrows

defer

用来定义以 任何方式 退出代码块前,必须要执行的代码。

不管是正常方式,还是异常退出,还是return,

func run() -> Void {    defer {        print("退出前一定会执行1")    }    defer {        print("退出前一定会执行2")    }        print("xxxxx")}
xxxxx退出前一定会执行2退出前一定会执行1

注意:defer 的定义顺序与执行顺序相反

以上是关于Swift 异常处理的主要内容,如果未能解决你的问题,请参考以下文章

使用片段中的处理程序时出现非法状态异常

如何使用原生崩溃报告在 Swift 4 中实现异常/错误处理?

swift - 异常处理

Java异常处理机制

swift常用代码片段

Swift 2.0 异常处理