美文网首页
错误处理

错误处理

作者: 曹来东 | 来源:发表于2019-07-16 17:55 被阅读0次

错误类型

  • 语法错误(编译报错)
  • 逻辑错误
  • 运行时错误(可能会导致闪退,一般也叫做异常)

自定义错误

  • Swift中可以通过Error协议自定义运行时的错误信息
  • 函数内部通过throw抛出自定义Error,可能会抛出Error的函数必须加上throws声明
  • 需要使用try调用可能会抛出Error的函数
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
}
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, 11)

do-catch

  • 可以使用do-catch捕捉Error
  • 抛出Error后,try下一句直到作用域结束的代码都将停止运行
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 test() {
    print(1111)
    do {
        print(2222)
        print(try divide(20, 0))
        print(33333)
    } catch let SomeError.illegalArg(msg) {
        print("参数异常",msg)
    } catch let SomeError.outOfBounds(size, index) {
        print("下标越界:","size = \(size)","index = \(index)")
    } catch let SomeError.outOfMemory {
        print("内存溢出")
    } catch {
        print("其他错误")
    }
    print(44444)
}
test()
//打印结果
1111
2222
参数异常 0不能作为除数
44444

处理Error的两种方式

  • 通过do-catch捕捉Error
  • 不捕捉Error,在当前函数增加throws声明.Error将自动抛给上层函数.如果顶层函数(main函数)依然没有捕捉到 Error,那么程序将终止
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 test() throws {
    print(1111)
    print(try divide(20, 0))
    print(22222)
}
try test()
//打印结果
//1111
//Fatal error: Error raised at top level:

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 test() throws {
    print(1111)
    do {
        print(222)
        print(try divide(20, 0))
        print(3333)
    } catch let error as SomeError {
        print(error)
    }
    print(444)
}
try test()
//打印结果
1111
222
illegalArg("0不能作为除数")
444

try? try!调用可能会抛出Error的函数,这样就不用去处理Error

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 test() {
    print(111)
    var result1 = try? divide(20, 10)//optional(2) Int?
    var result2 = try? divide(20, 0) //nil
    var result3 = try! divide(20, 10) //2 Int
    print(2)
}
test()
//111
//2

a b是等价的

var a = try? divide(20, 10)
var b : Int?
do {
   b = try divide(20, 10)
} catch let error as SomeError {
    print(error)
}

rethrows

  • rethrows表明: 函数本身不会抛出错误,但调用闭包参数抛出错误,那么他会将错误向上抛
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 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)

defer

  • defer语句: 用来定义以任何方式(抛错误,return等)离开代码快前必须要执行的代码
  • defer语句将延迟至当前作用域结束之前执行
  • defer语句的执行顺序与定义顺序相反
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 open(_ fileName: String) -> Int {
    print("open")
    return 0
}
func close(_ file: Int) {
    print("close")
}
func processFile(_ filename: String) throws {
    let file = open(filename)
    defer {
        close(file)
    }
    //使用file
    //...
    try divide(20, 0)
    
    //close将会在这里调用
}
try processFile("test.txt")
//open
//close
//Fatal error: Error raised at top level:
func fn1() {
    print("fn1")
}
func fn2() {
    print("fn2")
}

func test() {
    defer {
        fn1()
    }
    defer {
        fn2()
    }
}
test()
//打印
fn2
fn1

相关文章

网友评论

      本文标题:错误处理

      本文链接:https://www.haomeiwen.com/subject/xzotlctx.html