Swift(学习):错误处理(自定义错误,do-catch捕捉错误,处理Error,try?,try1,rethrows,defer,assert,fatalError)

本文深入探讨Swift中的错误处理机制,包括常见的开发错误类型、自定义错误的定义与抛出、do-catch结构的使用及异常处理流程。同时,介绍了如何在多级函数调用中处理错误,并展示了assert和fatalError等特殊错误处理手段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

错误类型

  • 开发过程常见的错误:
  1. 语法错误(编译报错)
  2. 逻辑错误 
  3. 运行时错误(可能会导致闪退,一般也叫做异常
  4. ......

自定义错误

  • Swift中可以通过Error协议自定义运行时的错误信息
enum SomeError : Error {
    case illegalArg(String)
    case outOfBounds(Int, Int)
    case outOfMemory
}
  • 函数内部通过throw抛出自定义Error,可能会抛出Error的函数必须加上throws声明
func devide (_ num1: Int, _ num2: Int) throws -> Int {
    if num2 == 0 {
        throw SomeError.illegalArg("0不能做除数")
    }
    return num1 / num2
}
  • 需要使用try调用可能会抛出Error的函数
var result = try devide(20, 10)

do-catch

  • 可以使用do-catch捕捉Error
enum SomeError : Error {
    case illegalArg(String)
    case outOfBounds(Int, Int)
    case outOfMemory
}

func devide (_ num1: Int, _ num2: Int) throws -> Int {
    if num2 == 0 {
        throw SomeError.illegalArg("0不能做除数")
    }
    return num1 / num2
}

//var result = try devide(20, 10)

func test() {
    print("1")
    do {
        print("2")
        print("结果正确:",try devide(20, 2))
        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
结果正确: 10
3
4

 上面对do-catch也可以简写为:

也可以写为:

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

一旦捕获到异常,try作用域内try之后的代码将不会再执行,代码如下:

enum SomeError : Error {
    case illegalArg(String)
    case outOfBounds(Int, Int)
    case outOfMemory
}

func devide (_ num1: Int, _ num2: Int) throws -> Int {
    if num2 == 0 {
        throw SomeError.illegalArg("0不能做除数")
    }
    return num1 / num2
}

//var result = try devide(20, 10)

func test() {
    print("1")
    do {
        print("2")
        print("结果正确:",try devide(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

由上可以看出:一旦捕获到异常,try作用域内try之后的代码将不会再执行,比如do{ }方法内的print("3")就不会执行,但是try作用域外的可以执行,比如print("4")


处理Error

  • 处理Error的2种方式
  1. 通过do-catch捕捉Error
  2. 不捕捉Error,在当前函数增加throws声明,Error将自动抛给上层函数 ,如果最顶层函数(main函数)依然没有捕捉Error,那么程序将终止
enum SomeError : Error {
    case illegalArg(String)
    case outOfBounds(Int, Int)
    case outOfMemory
}

func devide (_ num1: Int, _ num2: Int) throws -> Int {
    if num2 == 0 {
        throw SomeError.illegalArg("0不能做除数")
    }
    return num1 / num2
}

当顶层函数没有捕捉Error,程序终止报错如下:

 

捕捉Error的as书写方式:

捕捉Error的is书写方式:

 输出结果:

  • 当错误处理被多个函数调用时,有两种书写方式:
//第一种
func test0() {
    test1()
}

func test1() {
    test2()
}

func test2() {
    do {
        print(try devide(200, 0))
    } catch is SomeError {
        print("This is SomeError")
    } catch {
        print("Error")
    }
}
//第二种
func test0() throws {
   try test1()
}

func test1() throws{
   try test2()
}

func test2() throws{
    do {
        print(try devide(200, 0))
    } catch is SomeError {
        print("This is SomeError")
    }
}

try test0()

try?、try!

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

  • a、b是等价的

这里可以看出当divide(20,0)抛出异常时,不会给b赋值,b为nil,跑到catch也会赋值为nil,所以a和b等价


rethrows

  • rethrows表明:函数本身不会抛出错误,但调用闭包参数抛出错误,那么它会将错误向上抛

 

 此处的divide方法沿用之前的


defer

defer语句:用来定义以任何方式(抛错误、return等)离开代码块前必须要执行的代码 

defer语句将延迟至当前作用域结束之前执行

  此处的divide方法沿用上面的

  • defer语句的执行顺序与定义顺序相反


assert(断言)

  • 很多编程语言都有断言机制,不符合指定条件就抛出运行时错误,常用于调试(Debug)阶段的条件判断
  • 默认情况下,Swift的断言只会在Debug模式下生效,Release模式下会忽略

当v2 != 0时,会抛出错误

  • 增加Swift Flags修改断言的默认行为
  1. -assert-config Release:强制关闭断言
  2. -assert-config Debug:强制开启断言

上图是Debug模式下强制关闭断言,和Release模式下强制开启断言


fatalError

  • 如果遇到严重问题,希望结束程序运行时,可以直接使用fatalError函数抛出错误(这是无法通过do-catch捕捉的错误)
  • 使用了fatalError函数,就不需要再写return

  • 在某些不得不实现、但不希望别人调用的方法,可以考虑内部使用fatalError函数

  走到var stu2 = Student()运行时会报错

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

06-13 383
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值