美文网首页
14-错误处理

14-错误处理

作者: bytebytebyte | 来源:发表于2020-10-26 12:56 被阅读0次
    //错误处理1-7
    class Person {
        static var age = 0
        static func run() {}
    }
    Person.age = 10
    Person.run()
    //等价汇编代码也是一样的
    Person.self.age = 10
    Person.self.run()
    
    //四个等价汇编代码也是一样的
    var p0 = Person() //init()
    var p1 = Person.self() //init()
    var p2 = Person.init() //init()
    var p3 = Person.self.init() //init()
    
    func test(_ cls: AnyClass) {}
    test(Person.self)//Person.self元类类型
    
    //1.自定义错误
    //swift中可以通过error协议自定义运行时的错误信息
    enum SomeError : Error {
        case illegaArg(String)
        case outOfBounds(Int, Int)
        case outOfMemory
    }
    //函数内部通过throw抛出自定义Error,可能会抛出Error的函数必须加上throws声明
    func divide(_ num1: Int, _ num2: Int) throws -> Int {
        if num2 == 0 {
            throw SomeError.illegaArg("0不能作为除数")
        }
        return num1 / num2
    }
    func test0() throws {
        print("1")
        try test1()
        print("2")
    }
    func test1() throws {
        print("3")
        try test2()
        print("4")
    }
    func test2() throws {
        print("5")
        print(try divide(200, 0)) //需要通过try调用可能会抛出Error的函数
        print("6")
    }
    //try test0()//1 3 5 //注释掉这行test3才会执行
    
    //2.do-catch:可以用do-catch捕捉Error
    func test3() {
        print("1")
        do {
            print("2")
            print(try divide(20, 0))
            print("3")
        }catch let SomeError.illegaArg(msg) {
            print("参数异常:",msg)
        }catch let SomeError.outOfBounds(size,index) {
            print("下标越界:","size=\(size)","index=\(index)")
        }catch SomeError.outOfMemory {
            print("内存溢出")
        }catch {
            print("其他错误")
        }
        print("4")
    }
    //test3()
    /*
     1
     2
     参数异常: 0不能作为除数
     4
     */
    
    do {
        try divide(20, 0)
    } catch let error { //let error 去掉也行 do catch默认有error
        switch error {
        case let SomeError.illegaArg(msg):
            print("参数错误:",msg)
        default:
            print("其他错误")
        }
    }
    //参数错误: 0不能作为除数
    
    //3.处理Error
    //处理Error的2中方式
    //(1)通过do-catch捕捉error
    //(2)不捕捉Error,在当前函数增加throws声明,Error将自动抛给上层函数,如果最顶层函数(main函数)依然没有捕捉Error,那么程序将终止
    func test4() throws {
        print("1")
        print(try divide(20, 0))
        print("2")
    }
    //try test4()
    /*
     参数错误: 0不能作为除数
     1
     Playground execution terminated: An error was thrown and was not caught:
     ▿ SomeError
       - illegaArg : "0不能作为除数"
     */
    
    func test5() throws {
        print("1")
        do {
            print("2")
            print(try divide(20, 0))
            print("3")
        } catch let error as SomeError {
            print(error)
        }
        print("4")
    }
    //try test5()
    /*
     参数错误: 0不能作为除数
     1
     2
     illegaArg("0不能作为除数")
     4
     */
    
    //4.try?、try!
    //可以用try?、try!调用可能会抛出Error的函数,这样就不用去处理Error
    func test6() {
        print("1")
        var result1 = try? divide(20, 10)
        print(result1)//Optional(2),Int?
        var result2 = try? divide(20, 0)
        print(result2)// nil
        var result3 = try! divide(20, 10)
        print(result3)//2 Int
        print("2")
    }
    test6()
    //变量a、b是等价的
    var a = try? divide(20, 0)
    var b: Int?
    do {
        b = try divide(20, 0)
    } catch { b = nil }
    print("------")
    //5.rethrows表明:函数本身不会抛出错误,但调用闭包参数抛出错误,那么它会将错误向上抛
    func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows {
        print(try fn(num1, num2))
    }
    //try exec(divide, 20, 0)
    /*
     Playground execution terminated: An error was thrown and was not caught:
     ▿ SomeError
       - illegaArg : "0不能作为除数"
     */
    
    //5.defer
    /*
     defer语句:用来定义以任何方式(抛错误、return等)离开代码块前必须要执行的代码,defer语句将延迟至当前作用域结束之前执行
     */
    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
     Playground execution terminated: An error was thrown and was not caught:
     ▿ SomeError
       - illegaArg : "0不能作为除数"
     */
    
    //6.assert断言
    /*
     不符合指定条件就抛出运行时错误,常用于调试阶段的条件判断
     默认情况下,swift的断言只会在debug模式下生效,release模式下会忽略.
     但增加swift flags修改断言的默认行为:
     -assert-config Release:强制关闭断言
     -assert-config Debug:强制开启断言
     */
    func div(_ v1: Int, _ v2: Int) -> Int {
        assert(v2 != 0, "除数不能为0") //崩溃在这里不会往下走
        return v1 / v2
    }
    //print(div(20, 0))
    
    //7.fatalError:崩溃
    //如果遇到严重问题,希望结束运行程序时,可以直接使用fatalError函数抛出错误,这是无法通过do-catch捕捉的错误
    func te(_ num: Int) -> Int {
        if num >= 0 {
            return 1
        }
        fatalError("num 不能小于0") //使用了fatalError就不需要写return
    }
    //te(-1)
    
    //某些不得不实现、但不希望别人调用的方法,可以考虑内部使用fatalError
    class Cat { required init(){} }
    class Tiger : Cat {
        required init() {
            fatalError("don't call tiger.init")
        }
        init(score: Int) {}
    }
    var t1 = Tiger(score: 98)
    //var t2 = Tiger()
    

    相关文章

      网友评论

          本文标题:14-错误处理

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