swift 异常的捕获与处理

** 异常的抛出与传递

    swfit中,所有的错误和异常都由Error协议来指定。

    开发者可以编写自定义的枚举类型,使其遵守Error协议来描写所需求的异常类型

    函数中产生的异常只能在函数内部解决,开发者也可以使用throws关键字将此函数声明为可抛异常函数,此类声明则允许开发者在函数外解决函数内部抛出的异常

** 异常的捕获与处理

    系统为我们提供了三种异常处理的方法:

        <1> 使用do-catch结构来捕获处理异常、将异常映射为optional值,终止异常传递

        <2> 使用try?来调用函数可以将异常映射为Optional值

        <3> 使用try!来强制终止异常的传递

    do-catch:do-catch结构是swift语言中处理异常最常用的方法,开发者需要将可能抛出的异常的代码放入do结构中,如果这部分代码中有抛出异常,则会从catch块中寻找对应的异常类型,如果找到对应的,则会执行此catch块中的异常处理代码.

   使用do-catch处理异常可以根据异常类型分别提供处理方案,保证代码的健壮与可控性。

    try?:有些时候开发者可能并不关心产生异常的类型和原因,只需要知道有没有产生异常,对于这种情况,使用do-catch结构会显得十分繁琐冗余。

    try?可以将异常映射为optional值,如果函数正常运行,没有抛出异常,则正常返回,如果函数执行出错,抛出了异常,则会返回optional值nil。

    使用try?调用函数可以将异常映射为optional值

    try!:当开发者能够保证此函数一定不会抛出异常时,便可以使用try!来强制终止异常的传递,然而这么做有一定风险,如果这个函数真的抛出了异常,则会产生运行时错误

** 延时执行结构

    延时执行结构:延时构造语句lazy的作用是降低复杂类实例构造时所消耗的时间,swift语言中还提供了一种延时执行结构,defer{}

        作用:在函数中使用延执行结构可以保证结构中的代码块始终在函数要结束时执行

        使用场景:延时执行结构常被用来释放函数中所使用的一些资源和关闭文件等操作

    延时执行结构存在的意义:

        开发者会疑惑,如果想让一部分代码在函数结束前才执行,那么直接将它放在函数最后不就行了嘛?实际情况并非如此:

        在函数中,经常会由于特殊情况提前被break(中断)或者return(返回),或者一个复杂函数很可能会因为抛出异常而被中断,这些情况会造成函数的结束。

        使用延时执行语句可以保证无论函数因为何种原因结束,在结束前都会执行延时结构块中代码

//使用throws关键字,以及使用try?做异常处理

//一个开水阀出水的场景,假设水滴的个数,n = 0 水阀坏了,n < 5停水了, n > 5 水阀坏了
//定义异常
enum OpenWaterError : Error{
    case NoWater    //停水了
    case FMBroken   //水阀坏了
}
class OpenWaterWork{
    
    //使用throws关键字将此函数声明为可抛异常函数
    func openWater(droplets : Int)throws {
        if droplets == 0 {
            throw OpenWaterError.FMBroken
        }
        else if droplets > 0, droplets < 5{
            throw OpenWaterError.NoWater
        }
        else{
            print("The Water is OK!")
        }
    }
}

//使用throws,与do-catch结构
//定义异常
enum MyError:Error{
    case DesTroyError
    case NormalError
    case SimpleError
}
class MyErrorWork{
    //自定义一种异常类型,之后在代码中通过throw关键字进行异常的抛出
    func useThrowToError(isThrow:Bool)throws{
        if isThrow {
            print("throw MyError.DesTroyError, finished!")
            throw MyError.DesTroyError
        }
        else{
            print("this is no error!")
        }
    }
    
    func useTryError()throws{
        print("This is no error, in use try! error.")
    }
}

//延时执行结构
class DelayedExecution{
    
    func temError()throws -> Void{
        
        defer{
            print("Delayed Execution Last Work!")
        }
        print("handle")
        //抛出异常
        throw MyError.DesTroyError
    }
}

class ErrorThrow: NSObject {
    
    //使用throws,与do-catch结构
    func useMyErrorWork(){
        
        let myError = MyErrorWork()
        
        //使用do-catch结构去处理抛出的异常
        do {
            try myError.useThrowToError(isThrow: true)
        } catch MyError.DesTroyError {
            print("DesTroyError!")
        }catch MyError.NormalError{
            print("NormalError!")
        }catch MyError.SimpleError{
            print("SimpleError!")
        }catch{
            print("other error")
        }
        /*打印信息:
         throw MyError.DesTroyError, finished!  在MyErrorWork中函数抛出的异常
         DesTroyError!  在do-catch结构中处理异常所打印的信息
         
        */
    }

    //使用throws关键字,以及使用try?做异常处理
    func useErrorInOpenWater(){
        
        let opt = OpenWaterWork()
        //直接这样调用只写了throws的函数,函数中值throw抛出了异常,但没有使用try等去处理异常会报错
        //opt.openWater(droplets: 1)  //Call can throw, but it is not marked with 'try' and the error is not handled
        let op_result: ()? = try?opt.openWater(droplets: 1)
        if op_result == nil{
            print("执行失败")
        }else{
            print("执行成功")
        }
        /* 打印的信息:
            执行失败   op_result = nil此时打印了这个结果,因为openWater函数里有抛出异常,而可选值返回的是nil
        */
        
        //注意:返回值Void并不是nil,Void是空类型,nil是Optional类型中的一种特殊值。由于try?语法的存在,结合if-let语句,开发者可以写出十分飘逸的异常处理代码。我们可以把代码优化写,如下这样写:
        if let _ = try?opt.openWater(droplets: 1){
            print("Successed")
        }else{
            print("Failed")
        }
        /* 打印的信息:
            Failed  if的判断条件不为真,因此进入else,因为optional返回的是nil,此时openWater函数有异常抛出
        */
    }
    
    //使用try!
    func useErrorTry(){
        
        let myError = MyErrorWork()
        //此时调用的函数如果产生了异常,就会发生运行时错误,此处使用了一个throws的函数直接报错了
        //try! myError.useThrowToError(isThrow: true)
        //报错:Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: SwiftCode.MyError.DesTroyError
        try! myError.useTryError()  //此时终止了异常的传递
        print("This is use try! in useErrorTry.")
        /* 打印信息:
            This is no error, in use try! error.    函数useTryError()被执行时打印的
            This is use try! in useErrorTry.        try!强制后,打印的后面一句print
        */
    }
    
    //延时执行结构
    func delayedExecution(){
        
        let de = DelayedExecution()
        //使用延时执行结构
        //这里不处理异常,同样会报错
        //try de.temError()   //Errors thrown from here are not handled
        if let _ = try? de.temError(){
            print("try succeded in delayed execution!")
        }
        else{
            print("try failed in delayed execution!")
        }
        /* 打印信息
         handle     //defer延时结构后面的代码先被执行了
         Delayed Execution Last Work!   //defer结构中的print代码在函数temError()中最后执行
         try failed in delayed execution!   //temError()抛出了一个异常,optional选择结构返回了nil,执行了else打印的信息
        */
        
    }
    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SwiftUI 和 Combine 是苹果公司推出的两个重要的编程框架,用于开发iOS和macOS应用程序。SwiftUI 是用于构建用户界面的声明式框架,它使用Swift语言来简化用户界面的构建过程,使开发者能够更容易地创建动态、交互式的应用程序界面。Combine 是用于处理数据流的框架,它使用Swift语言来简化数据流的管理和处理,使开发者能够更方便地处理异步事件和数据流。这两个框架的结合使用,大大简化了iOS和macOS应用程序的开发。 在SwiftUI中,开发者可以利用声明式语法来描述用户界面的外观和行为,而不需要编写大量的代码。与传统的UIKit不同,SwiftUI能够更好地适应不同的设备和屏幕尺寸。Combine框架则提供了一种用于处理异步数据流的方式,并且能够轻松地将多个数据流进行组合和转换,使得在应用程序中处理数据变得更加简单和灵活。 通过结合使用SwiftUI和Combine,开发者可以实现一个高效、响应式的应用程序,能够更好地处理用户界面和数据的交互。而且SwiftUI和Combine都是使用Swift语言进行编写的,因此它们可以更好地与现有的Swift代码进行集成和共享。 总的来说,SwiftUI和Combine框架的出现,使得iOS和macOS应用程序的开发变得更加简单、高效和灵活,为开发者提供了一种全新的方式来构建用户界面和处理数据流。随着SwiftUI和Combine的不断发展和完善,它们将成为开发iOS和macOS应用程序的重要工具之一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值