15-Swift错误处理

2020-12-18  本文已影响0人  一抹相思泪成雨

1.自定义错误

/// Swift中可以通过Error协议自定义运行时的错误信息
enum SomeError : Error {
    case illegalArg(String)
    case outOfBounds(Int, Int)
    case outOfMemory
}

/// 函数内部通过throw抛出自定义Error,可能会抛出Error的函数必须加上throws声明
func divide(_ num1: Int, _ num2: Int) throws -> Int {
    if num2 == 0 {
        throw SomeError.illegalArg("0不能作为除数")
    }
    return num1 / num2
}
/// 需要使用try调用可能会抛出的Error的函数
var result = try divide(20, 10)

2.do-catch

/// 可以使用do-catch捕捉Error
func test() {
    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")
}

//test()
// 1
// 2
// 参数异常:0不能作为除数
// 4

do {
   try divide(20, 0)
} catch let error {
    switch error {
    case let SomeError.illegalArg(msg):
        print("参数错误:", msg)
    default:
        print("其它错误")
    }
}

3.处理Error

如果顶层函数(main函数)依然没有捕捉Error,那么程序将终止

func test1() throws {
    print("1")
    print(try divide(20, 0))
    print("2")
}
//try test1()

do {
    print(try divide(20, 0))
} catch is SomeError {
    print("SomeError")
}

func test2() throws {
    print("1")
    do {
        print("2")
        print(try divide(20, 0))
        print("3")
    } catch let error as SomeError {
        print(error)
    }
    print("4")
}
//try test2()
// 1
// 2
// illegalArg("0不能作为除数")
// 4

4.try?、 try!

/// 可以使用try?、try!调用可能会抛出Error的函数,这样就不用去处理Error
func test3() {
    print("1")
    print(try? divide(20, 10))   // Optional(2), Int?
    print(try? divide(20, 0))    // nil
    print(try! divide(20, 10))   // 2, Int
    print("2")
}
test3()

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

5.rethrows

func exec(_ func1:(Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows {
//    print(try func1(num1, num2))
}
// Fatal error: Error raised at top level
try exec(divide, 20, 0)

6.defer

/// defer语句将延迟至当前作用域结束之前执行
func open(_ filename: String) -> Int {
    print("open")
    return 0
}
func close(_ file: Int) {
    print("close")
}

/// defer语句的执行顺序与定义顺序相反
func fn1() {print("fn1")}
func fn2() {print("fn2")}
func test4() {
    defer { fn1() }
    defer { fn2() }
}
test4()
// fn2
// fn1

func processFile(_ filename: String) throws {
    let file = open(filename)
    defer {
        close(file)
    }
    try divide(20, 0)
}
//try processFile("test")

// open
// close
// Fatal error: Error raised at top level

7.assert (断言)

func divide1(_ v1: Int, _ v2: Int) -> Int {
    assert(v2 != 0, "除数不能为0")
    return v1 / v2
}
//print(divide1(20, 0))

/// 增加Swift Flags修改断言的行为
/// -assert-config Release : 强制关闭断言
/// -assert-config Debug: 强制开启断言

8.fatalError

func test(_ num: Int) -> Int {
    if num >= 0 {
        return 1
    }
    fatalError("num 不能小于0")
}
/// 在某些不得不实现,但不希望别人调用的方法,可以考虑内部使用fatalError函数
class Person { required init() {} }

class Student: Person {
    required init() { fatalError("don't call Student.init")}
    init(score: Int) {}
}
var stu1 = Student(score: 98)
//var stu2 = Student()

9.局部作用域

do {
    print("123")
}
上一篇 下一篇

猜你喜欢

热点阅读