# Swift 错误处理 ```swift 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 } func testErrorCapture() { 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") } testErrorCapture() // console 1 2 参数异常: 分母不能为0 4 ``` 如果 `try divide(20, 0)` 则输出: 1 、2、参数异常: 分母不能为0、4 如果 `try divide(20, 2)` 则输出: 1 、2、10、3、4 说明:如果 do 抛出异常,则作用域内的后续的其他代码都不会被执行 ## Error 处理方式 - 通过 do-catch 捕捉 Error - 不捕捉 Error,在当前函数增加 throws 声明,Error 继续向上层调用函数抛 ```swift func divide(_ num1: Int, _ num2: Int) throws -> Int { if num2 == 0 { throw SomeError.illegalArg("分母不能为0") } return num1/num2 } func safeDivide(_ num1: Int, _ num2: Int) -> Int { var result:Int = 0 do { result = try divide(num1, num2) } catch let SomeError.illegalArg(msg) { print("参数异常:", msg) } catch let SomeError.outOfBounds(size, index) { print("下标越界: size = \(size), index = \(index)") } catch SomeError.outOfMemory { print("内存溢出") } catch { print("其他异常") } return result } print("1") print(safeDivide(8, 2)) print("3") // console 1 4 3 ``` - 如果有些错误不需要向上抛,可以用 `try?` ` try!` 调用可能会抛出 Error 的函数,这样就不需要去处理 Error ```swift func testIgnoreError () { print("1") print(try? divide(10, 0)) print("2") } testIgnoreError() // console 1 nil 2 ``` ## rethrows 如果一个函数本身不会抛出错误,但某个参数是闭包,且闭包抛出错误,那么函数需要用 `rethrows` 向上抛出错误 ```swift func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows { print(try fn(num1, num2)) } func testCaptureClouserError () { do { try exec(divide, 20, 0) } catch let error { switch error { case let SomeError.illegalArgs(msg): print("参数异常:", msg) break case let SomeError.outOfBounds(size, index): print("下标越界: size = \(size), index = \(index)") break case SomeError.outOfMemory : print("内存溢出") break default: print("其他异常") } } } testCaptureClouserError() // 参数异常: 分母不能为0 ```