Files
knowledge-kit/Chapter1 - iOS/1.118.md
2024-04-27 13:01:58 +08:00

3.1 KiB
Raw Blame History

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 继续向上层调用函数抛

    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

    func testIgnoreError () {
        print("1")
        print(try? divide(10, 0))
        print("2")
    }
    testIgnoreError()
    // console
    1
    nil
    2
    

rethrows

如果一个函数本身不会抛出错误,但某个参数是闭包,且闭包抛出错误,那么函数需要用 rethrows 向上抛出错误

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