swift 错误处理

详解Swift中的错误处理 前言任何代码都会发生错误,这些错误有些是可以补救的,有些则只能让程序崩溃。良好的错误处理能够让你的代码健壮性提高,提高程序的稳定性。本文的Swift版本:Swift 3Objective C返回nil如果出错了,就返回空是Objective C中的一种常见的处理方式。因为在Objective C中,向nil发送消息是安全的。比如:- (instancetype)init { self = [ 阅读详情

错误处理是响应错误以及从错误中恢复的过程。swift提供了在运行时对可恢复错误的抛出、捕获、传递和操作的一等公民支持。

某些操作无法保证总是执行完所有代码或总是生成有用的结果。可选类型可用来表示值缺失,但是当某个操作失败时,最好能得知失败的原因,从而可以做出相应的应对。

举个例子,假如有个从磁盘上的某个文件读取数据并进行处理的任务,该任务会有多种可能失败的情况,包括制定路径下文件并不存在,文件不具有可读权限,或者文件编码格式不兼容。区分这些不同的失败情况可以让程序解决并处理某些错误,然后把它解决不了的错误报告给用户。

表示并抛出错误

在swift中,错误用符合Error协议的类型的值来表示。这个空协议表明该类型可以用于错误处理。
swift的枚举类型尤为适合构建一组相关的错误状态,枚举的关联值还可以提供错误状态的额外信息。
    enum VendingMachineError:Error {
        case invalidSelection
        case insufficientFunds(coinsNeeded:Int)
        case outOfStock
    }
抛出一个错误可以让你表明有意外情况发生,导致正常的执行流程无法继续执行。抛出错误使用throw关键字。
throw VendingMachineError.outOfStock

处理错误

某个错误被抛出时,附近的某部分代码必须负责处理这个错误。
swift中有4种处理错误的方式。可以把函数抛出的错误传递给调用此函数的代码、用do-catch语句处理错误、将错误作为可选类型处理、或者断言此错误根本不会发生。
当一个函数抛出了一个错误时,程序流程会发生改变,所以重要的是能迅速识别代码中会抛出错误的地方。为了标识出这些地方,在调用一个能抛出错误的函数、方法或者构造器之前,加上try关键字,或者try?或try!这种变体。

用throwing函数传递错误

为了表示一个函数、方法或、构造器可以抛出错误,在函数声明的参数列表之后加上throws关键字,一个标有throws关键字的函数被称为throwing函数。
 struct Item {
     var price: Int
     var count: Int
 }
 class VendingMachine {
     var inventory = [
         "Candy Bar": Item(price: 12, count: 7),
         "Chips": Item(price: 10, count: 4),
         "Pretzels": Item(price: 7, count: 11)
     ]
     var coinsDeposited = 0
     func dispenseSnack(snack: String) {
         print("Dispensing \(snack)")
     }
     func vend(itemNamed name: String) throws {
         guard let item = inventory[name] else {
             throw VendingMachineError.InvalidSelection
         }
         guard item.count > 0 else {
             throw VendingMachineError.OutOfStock
}
         guard item.price <= coinsDeposited else {
             throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
         coinsDeposited -= item.price
         var newItem = item
         newItem.count -= 1
         inventory[name] = newItem
         print("Dispensing \(name)")
     }
}

在 vend(itemNamed:) 方法的实现中使用了 guard 语句来提前退出方法,确保在购买某个物品所需的条件中,有任一条件不满足时,能提前退出方法并抛出相应的错误。由于 throw 语句会立即退出方法,所以物品只有在所有条件都满足时才会被售出。

因为 vend(itemNamed:) 方法会传递出它抛出的任何错误,在你的代码中调用此方法的地方,必须要么直接处理这些错误——使用 do-catch 语句, try? 或 try! ;要么继续将这些错误传递下去。例如下面例子中, buyFavoriteSnack(_:vendingMachine:) 同样是一个 throwing 函数,任何由 vend(itemNamed:) 方法抛出的错误会一直被传递到 buyFavoriteSnack(person:vendingMachine:) 函数被调用的地方。 

let favoriteSnacks = [
     "Alice": "Chips",
     "Bob": "Licorice",
     "Eve": "Pretzels",
 ]
 func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
     let snackName = favoriteSnacks[person] ?? "Candy Bar"
     try vendingMachine.vend(itemNamed: snackName)
 }

上例中, buyFavoriteSnack(person:vendingMachine:) 函数会查找某人最喜欢的零食,并通过调用 vend(itemNamed:) 方法来尝试为他们购买。因为 vend(itemNamed:) 方法能抛出错误,所以在调用的它时候在它前面加了 try 关键字。

throwing 构造器能像 throwing 函数一样传递错误.例如下面代码中的 PurchasedSnack 构造器在构造过程中调用了throwing函数,并且通过传递到它的调用者来处理这些错误。 

 struct PurchasedSnack {
     let name: String
     init(name: String, vendingMachine: VendingMachine) throws {
         try vendingMachine.vend(itemNamed: name)
         self.name = name
     }
}

用do-catch处理错误

可以使用一个 do-catch 语句运行一段闭包代码来处理错误。如果在 do 子句中的代码抛出了一个错误,这个错误会与 catch 子句做匹配,从而决定哪条子句能处理它。

下面是 do-catch 语句的一般形式: 

 do {
     try expression
     statements
 } catch pattern 1 {
     statements
 } catch pattern 2 where condition {
statements }

在 catch 后面写一个匹配模式来表明这个子句能处理什么样的错误。如果一条 catch 子句没有指定匹配模式,那么这条子句可以匹配任何错误,并且把错误绑定到一个名字为 error 的局部常量。 

catch子句不必将 子句中的代码所抛出的每一个可能的错误都作处理。如果所有 子句都未处理错误,错误就会传递到周围的作用域。然而,错误还是必须要被某个周围的作用域处理的——要么是一个外围的 do-catch错误处理语句,要么是一个 throwing 函数的内部。举例来说,下面的代码处理了枚举类型的全部枚举值,但是所有其它的错误就必须由它周围的作用域处理: 

var vendingMachine = VendingMachine()
 vendingMachine.coinsDeposited = 8
 do {
     try buyFavoriteSnack("Alice", vendingMachine: vendingMachine)
 } catch VendingMachineError.InvalidSelection {
     print("Invalid Selection.")
 } catch VendingMachineError.OutOfStock {
     print("Out of Stock.")
 } catch VendingMachineError.InsufficientFunds(let coinsNeeded) {
  
print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
 }

上面的例子中, buyFavoriteSnack(person:vendingMachine:) 函数在一个 try 表达式中调用,因为它能抛出错误。如果错误被抛出,相应的执行会马上转移到 catch 子句中,并判断这个错误是否要被继续传递下去。如果没有错误抛出, do 子句中余下的语句就会被执行。 

将错误转换成可选值

可以使用 try? 通过将错误转换成一个可选值来处理错误。如果在评估 try? 表达式时一个错误被抛出,那么表达式的值就是 nil 。例如,在下面的代码中, x 和 y 有着相同的数值和等价的含义: 

 func someThrowingFunction() throws -> Int {
     // ...
 }
 let x = try? someThrowingFunction()
 let y: Int?
 do {
     y = try someThrowingFunction()
 } catch {
y = nil }

如果 someThrowingFunction() 抛出一个错误, x 和 y 的值是 nil 。否则 x 和 y 的值就是该函数的返回值。注意,无论 someThrowingFunction() 的返回值类型是什么类型, x 和 y 都是这个类型的可选类型。例子中此函数返回一个整型,所以 x 和 y 是可选整型。

如果你想对所有的错误都采用同样的方式来处理,用 try? 就可以让你写出简洁的错误处理代码。例如,下面的代码用几种方式来获取数据,如果所有方式都失败了则返回 nil : 

 func fetchData() -> Data? {
     if let data = try? fetchDataFromDisk() { return data }
     if let data = try? fetchDataFromServer() { return data }
     return nil
}

禁用错误传递

有时你知道某个 throwing 函数实际上在运行时是不会抛出错误的,在这种情况下,你可以在表达式前面写 tr
y!
来禁用错误传递,这会把调用包装在一个不会有错误抛出的运行时断言中。如果真的抛出了错误,你会得到一个运行时错误。

例如,下面的代码使用了 loadImage(atPath:) 函数,该函数从给定的路径加载图片资源,如果图片无法载入则抛出一个错误。在这种情况下,因为图片是和应用绑定的,运行时不会有错误抛出,所以适合禁用错误传递: 

 let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

指定清理操作

可以使用 defer 语句在即将离开当前代码块时执行一系列语句。该语句让你能执行一些必要的清理工作,不管是以何种方式离开当前代码块的——无论是由于抛出错误而离开,还是由于诸如 return 或者 break 的语句。例如,你可以用 defer 语句来确保文件描述符得以关闭,以及手动分配的内存得以释放。

defer 语句将代码的执行延迟到当前的作用域退出之前。该语句由 defer 关键字和要被延迟执行的语句组成。延迟执行的语句不能包含任何控制转移语句,例如 break 或是 return 语句,或是抛出一个错误。延迟执行的操作会按照它们被指定时的顺序的相反顺序执行——也就是说,第一条 defer 语句中的代码会在第二条 defer 语句中的代码被执行之后才执行,以此类推。 

func processFile(filename: String) throws {
    if exists(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
while let line = try file.readline() { // 处理文件。
}
// close(file) 会在这里被调用,即作用域的最后。 }
}

上面的代码使用一条 defer 语句来确保 open(_:) 函数有一个相应的对 close(_:) 函数的调用。 



取自《the swift Programming language》中文版



















Swift 里错误处理 错误处理(Error handling)是响应错误以及从错误中恢复的过程。Swift 在运行时提供了抛出、捕获、传递和操作可恢复错误(recoverable errors)的一等支持(first-class support) 表示与抛出错误 Swift中错误用遵循Error协议的类型的值来表示。这个空协议表明该类型可以用于错误处理。 Swift的枚举类型适合构建一组相关的错误状态,枚举关联值还可以提供错误状态的额外信息 游戏中操作自动贩卖机 enum VendingMachineErro... 阅读详情

相关推荐

Apollo&Carla联合仿真环境搭建与实战调试

本文详细介绍了Apollo与Carla联合仿真环境的搭建与实战调试流程,涵盖硬件配置、软件依赖安装、Apollo环境配置、Carla仿真器安装、桥接服务设置以及常见问题解决方案。通过逐步指导,帮助开发者高效实现自动驾驶仿真测试,提升开发效率。

ee345的博客 200

swift4.0 throw错误处理

对于大部分现代化面向对象的编程语言都拥有结构化的错误处理语法特性,swift也不例外。当我们在一个方法或函数中实现某些功能时,如果遇到错误的用户输入则可能导致严重的异常问题,此时我们可以选择通过抛出异常的方式,将此错误送给函数调用者。 我们常用 try-catch 结构,不过在swift编程语言中没有引入专门的 try 语句块,而是直接调用之前的 do 语句块,仅仅将 try 作为抛出异常...

Lea__DongYang的博客 1434

基于资源预测的Agent弹性伸缩:在成本与响应延迟间寻找最佳平衡点

手动伸缩:完全由运维人员人工调整副本数或服务器数量,效率极低,现在基本只用于极小规模的业务。反应式伸缩:基于当前实时监控指标触发伸缩规则,比如CPU利用率超过70%就加2个副本,是目前应用最广泛的方案,典型代表是K8s HPA、KEDA。预测式伸缩:基于历史时序数据预测未来的负载,提前进行伸缩,解决反应式伸缩的滞后性问题,典型代表是AWS Predictive Scaling、阿里云预测式HPA。智能Agent伸缩。

SuperAGI2025 133

golang学习-panic

转载自 https://www.cnblogs.com/liuzhongchao/p/10112739.html package main import "fmt" func main() { //Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为, //将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。 //在Go语言中,使用多值返回来返回错误。不要用异常代替错误,

lilele12211104的专栏 337

XDMA 驱动安装与性能测试全流程解析

本文详细解析了XDMA驱动的完整安装与性能测试流程。从环境准备、源码获取、编译安装到驱动加载与设备验证,逐步指导用户打通FPGA加速卡与主机间的高速数据通道。重点介绍了如何通过官方测试脚本进行功能验证与带宽性能测试,帮助用户评估XDMA驱动的实际传输效能,为AI推理、高频交易等低延迟高带宽应用奠定基础。

weixin_29216049的博客 524

FPGA进位链(Carry Chain)实战:从Xilinx CARRY8原语到性能优化全解析

本文深入解析了FPGA进位链(Carry Chain)的原理与应用,重点剖析了Xilinx CARRY8原语的端口功能与内部机制。通过实测数据揭示了进位链的真实延迟特性与温度影响,并详细阐述了如何利用DI和S信号进行动态路径优化、实现减法运算与条件进位选择,从而有效提升设计性能。最后,文章探讨了系统级的流水线拆分、布局约束等实战优化策略与常见陷阱。

weixin_29313817的博客 449

Swift 异常处理

在上面的示例中,如果 makeRequest() 函数抛出 NetworkError.noConnection 异常,那么会执行对应的 catch 代码块并打印"网络连接失败"。在上面的示例中,不论 fetchData() 函数是否抛出异常,都会执行 finally 代码块中的 cleanup() 函数。当一个函数抛出异常时,它的调用者可以选择继续传播异常、捕获异常并处理,或者忽略异常。在上面的示例中,fetchData() 函数抛出的异常会传播给调用它的 do-catch 语句进行处理。

WEScript的博客 560

利用ADS设计射频功率放大器

利用ADS设计射频功率放大器 任务: 用飞思卡尔公司的功率放大器芯片ATF27s006NT1设计射频功放,芯片频率范围可达450MHz-3.6GHz。 功放指标: (1) 工作频率:500MHz (2) 增益:G>20dB (3) 电源:+28V (4) 最大输出功率:2W(33dBm) 设计思路 (1)安装DesignKit模型; (2)直流DC扫描; (3)稳定性分析; (4)偏置电路设计及整...

UVM频率 3万+

Swift 中 throws 异常抛出

一.异常抛出关键 throws 定义在函数结尾 如果函数有返回值 定义在 返回类型前如 :func throwDeliver(num:Int) throws -&gt;String二.定义方法//错误传递    @discardableResult    func throwDeliver(num:Int) throws -&gt;String {        print("错误传递")    ...

圣人男的博客 6480

python利用IQR方法与3σ方法进行异常值处理(含代码)

python利用IQR方法进行异常值处理

weixin_46713695的博客 2031

C++ Qt6 qml CMakeLists.txt如何添加qrc文件

本文介绍了在Qt6项目中如何通过CMake管理QML图片资源。相比Qt5的qmake,CMake需要手动创建qrc文件并配置CMakeLists.txt。关键步骤包括:1)创建resources.qrc文件并添加图片资源;2)在CMakeLists.txt中设置CMAKE_AUTORCC为ON开启自动资源处理;3)使用qt_add_resources将qrc文件绑定到项目。配置完成后,可通过"qrc:alias"方式引用资源图片,解决了相对路径管理复杂的问题。

琅嬛福地 1453

Swift——异常错误处理(throws)

如果在调用系统某一个方法时,该方法最后有一个throws。说明该方法会抛出异常。如果一个方法会抛出异常,那么需要对该异常进行处理。 在Swift 中提供三种处理异常的方式 方式一:try 方式 程序员手动捕捉异常 (一般不常用) 方式二:try?方式 (常用) 系统帮助我们处理异常,如果该方法出现了异常,则该方法返回nil.如果没有异常,则返回对应的对象。 方式三:tr

cym_bj 1317

Python 陌生代码库阅读之道:从零起步到一周掌控 5 万行老项目的实战策略

文中特别强调"自顶向下+画图+注释"的基础阅读心法,并提供了具体的代码示例和命令行技巧。对于大型项目,建议先建立核心流程的骨架认知,再逐步填充细节,同时注重文档化和测试覆盖率的提升。 掌握这套方法后,开发者可以将陌生代码库的阅读效率提升3倍以上,在一周内建立起对5万行级别项目的整体掌控力。

铭渊老黄 506

Swift 错误处理

错误处理(Error handing)是响应错误以及从错误中恢复的过程。Swift 在运行时提供了抛出、捕获、传递和操作可恢复错误(recoverable errors)的一等支持(first-class support)。某些操作无法保证总是执行完所有代码或生成有用的结果。可选类型用来表示值缺失,但是当某个操作失败时,理解造成失败的原因有助于你的代码做出相应的应对。

xiaoxiaobukuang的专栏 1203

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

错误处理原则及其在Swift中的应用

本文由两种内容组成,一部分是错误处理的思路,第二种是这种思路如何使用Swift来实现。前言错误处理是程序员最重要-也是最容易忽视的话题之一,程序员经常花费了大量的经历在打印大量日志,完善监...

淘系技术 2011

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

swift 抛出错误_Swift错误处理– Swift尝试,捕捉,抛出

swift 抛出错误Swift error handling is a very important aspect of writing better code. Swift try statement is used for error handling in swift programs. Let’s get started by launching XCode playground. Swi...

从零开始的教程世界 1288

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Swift-错误处理

错误处理(Error handling) 是响应错误以及从错误中恢复的过程。 Swift 在运行时提供了抛出、捕获、传递和操作可恢复错误(recoverable errors)的一等支持(first-class support)。 1. 表示与抛出错误 在 Swift 中,错误用遵循 Error 协议的类型的值来表示。这个空协议表明该类型可以用于错误处理。 Swift 的枚举类型尤为适合构建...

hkasdfiu12 272

swift 中错误处理

swift 中错误处理1. 开发环境说明2. 自定义错误类型3. try?的使用方式4. do...catch的使用5. try!的使用方式6. defer的使用7. 养眼图片一张 1. 开发环境说明 系统版本:macOS Catalina 10.15.4 Xcode版本: Version 11.5 (11E608c) swift版本: Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53). 2. 自定义错误类型 enu

xuanwenchao的专栏 784

Swift 中的错误处理

前言 将可能遇到的异常尽可能扼杀在编译期是 Swift 在安全性上至始至终贯彻的理念,本文接下来将讨论Swift中是如何进行错误处理的 (Error Handling)。 错误(Error) 可以简单的将错误划分为编译错误、逻辑错误以及运行时错误 编译错误 let a = 10 a = 20 // 编译器报错: Cannot assign to value: 'a' is a 'let' constant func name(v: Int) -> Int { return "hello"

Rey的技术博客 1465

Swift 2中的错误处理

我还没有遇到喜欢错误处理的程序员。 无论您是否喜欢,健壮的应用程序都需要以这样的方式来处理错误:该应用程序保持功能正常并在必要时通知用户。 像测试一样,它是工作的一部分。 1. Objective-C 在Objective-C中,忽略错误处理太容易了。 看下面的示例,其中我忽略了执行获取请求可能导致的任何错误。 // Execute Fetch Request NSArray *re...

代码教主 291

神奇的 Swift 错误处理

原文:Magical Error Handling in Swift 作者: Gemma Barlow 译者:kmyhy Swift 中的错误处理从 O-C 沿袭而来,但 Swift 1.0 之后逐渐发生了巨大改变。重要的改变发生在 Swift 2,它率先使用了“处理非异常的状态和条件”的做法,使你的 app 变得更加简单。类似于其它编程语言,在 Swift 中,选择使用哪种错误处理技

kmyhy的专栏 6173

Swift的错误处理机制是怎样的?

Swift的错误处理机制是一个强大而灵活的系统,它允许开发者以清晰、明确的方式处理程序中可能出现的各种错误情况。我们针对不同的错误类型编写了不同的catch代码块来处理这些错误。例如,当我们需要在一个不支持抛出错误的上下文中处理可能的错误时,我们可以返回一个可选类型,而不是抛出一个错误。总之,Swift的错误处理机制是强大而灵活的,它允许开发者以清晰、明确的方式处理程序中可能出现的各种错误情况。例如,我们可以定义一个自定义的错误类型,该类型包含有关错误的详细信息,并允许我们在捕获错误时执行特定的操作。

EugeneBecher的博客 772

swift3 错误处理

1.一般处理错误步骤:1.使用 Error 建立异常类型例://处理更细分的错误情况,错误类型须遵从Error协议 enum DogError : Error{ case NameInvalidError case AgeInvalidError case NameLengthError }2.使用 throws 来声明异常,用 throw 来抛出异常一个函数可以加上thro

shenhaifeiniao的博客 2003
上一篇: swift 析构器
下一篇: swift 可选链式调用
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值