Swift 错误处理理解-背书

186 阅读3分钟

简介

参考 - SwiftGG

为什么会写这遍文章呢?

  • 自己写一遍更容易理解
  • 参考文献虽然能阅读懂,但是长久不看忘记了,再看一遍,需要再阅读理解。没有看自己写的文章,容易理解
  • 一些细节问题理解,需要自己code一下,才能更动,比如case iswheredefer

错误处理

错误处理(Error handling) 是响应错误以及从错误中恢复的过程。Swift 在运行时提供了抛出、捕获、传递和操作可恢复错误(recoverable errors)的一等支持(first-class support)。

错误类型

在 Swift 中,错误要遵循 Error 协议的类型的值来表示。这个空协议表明该类型可以用于错误处理。

// 常用枚举表示错误类型
enum ThorwError: Error {
    case notValue
    case specificValue
}

处理错误

1、使用throw来抛出异常

throw ThorwError.notValue

2、使用 throwing 函数传递错误

// 函数抛出异常需要加上 throws 字段
func throwError(test: String) throws -> String {}
func throwError(test: String) throws {}

3、用 Do-Catch 处理错误

你可以使用一个 do-catch 语句运行一段闭包代码来处理错误。如果在 do 子句中的代码抛出了一个错误,这个错误会与 catch 子句做匹配,从而决定哪条子句能处理它。

func throwError(test: String) throws -> String {
        guard test == "" else {
            throw ThorwError.notValue
        }
        guard test == "test" else {
            throw ThorwError.specificValue
        }
        // 抛出异常,就不会向下执行代码了
        print("\(test)")
        return test
}

用法1: catch is 表示异常类型是否属于ThorwError 类型

do {
        let test = try throwError(test: "")
        print(test)
   } catch is ThorwError {
        print("notValue")
   } catch {
        print("specificValue")
   }

用法2: catch具体到错误类型处理

do {
        let test = try throwError(test: "")
        print(test)
   } catch ThorwError.notValue {
        print("notValue")
   } catch {
        print("specificValue")
   }

用法3:与where一起使用

enum NumberError: Error {
    case min
    case num(num: Int)
}

do {
        try numberErroe(num: 6)
   } catch NumberError.num(let number) where number > 6 {
       // 使用where进行多条件判断
        print("sss\(number)")
   } catch {
        print("sssa")
   }
 
func numberErroe(num: Int) throws {
        guard num < 5 else {
            throw NumberError.num(num: num)
        }
    }

注意:do-catch 必须要包含一个无条件的 catch{}

将错误转换成可选值

func some(num: Int) throws -> Int? {
    ......
}
// 当使用可选值时,可以使用try?
do {
    try? some(num: 5)
} catch {
}

禁用错误传递

有时你知道某个 throwing 函数实际上在运行时是不会抛出错误的,在这种情况下,你可以在表达式前面写 try! 来禁用错误传递,这会把调用包装在一个不会有错误抛出的运行时断言中。如果真的抛出了错误,你会得到一个运行时错误。

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

指定清理操作

defer 语句将代码的执行延迟到当前的作用域退出之前。该语句由 defer 关键字和要被延迟执行的语句组成。延迟执行的语句不能包含任何控制转移语句,例如 breakreturn 语句,或是抛出一个错误。延迟执行的操作会按照它们声明的顺序从后往前执行——也就是说,第一条 defer 语句中的代码最后才执行,第二条 defer 语句中的代码倒数第二个执行,以此类推。最后一条语句会第一个执行。

func processFile(filename: String) throws {
        if filename.count > 0 {
            print("a")
            defer {
                print("b")
            }
            print("c")
        }
}
// 打印结果
// a
// c
// b