Swift从入门到精通第十四篇 - 错误处理 初识
错误处理(学习笔记)
环境Xcode 11.0 beta4 swift 5.1
错误表现和抛出
- 在
swift中,错误由符合Error协议的类型值表示// 示例
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
// 抛出错误
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
- 在
错误处理
在 Swift 中有四种处理错误的方式:一、从函数中把错误传递出来;二、用
do-catch语句;三、作为可选值处理;四、用断言在 Swift 中错误处理与其它语言(包括OC)的异常类似,Swift 中错误处理不会涉及展开堆栈的调用,而堆栈的调用消耗是很大的,从性能的角度出发
throw语句的性能与return性能是一样的函数抛出错误,只有声明了
throws的函数才能往外抛出错误,如果不是则抛出的错误必须在函数内部处理func canThrowErrors() throws -> String
//
func cannotThrowErrors() -> String
示例代码
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 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)")
}
}
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) // 如果这里有错误,将会向外层抛
}
可抛出的初始化器也可以向外抛出错误
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
用
do-catch处理错误,一般格式如下do {
try expression
// statements
} catch pattern1 {
// statements
} catch pattern2 where condition {
// statements
} catch {
// statements
}
// catch 后的 pattern1 表示这个大括号内处理 pattern1 类型的错误,如果省略不写表示处理任何类型的错误且把错误绑定到一个常量 `error`
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
print("Success! Yum.")
} 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.")
} catch {
print("Unexpected error: \(error).")
}
// Prints "Insufficient funds. Please insert an additional 2 coins."
将错误转换为可选值
- 可以用
try?将错误转换为可选值,如果有错误抛出,计算try?表达式的值为nilfunc someThrowingFunction() throws -> Int {
// ....
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
}catch {
y = nil
}
// 如果函数 someThrowingFunction 抛出错误,则 x 的值为 nil;否则 x、y 就是函数返回的值,且此时x、y是可选值
- 如果想用
try?准确处理所有错误,如下示例func fetchData() -> Data? {
if let data = try? fecthDataFromDisk() { return data }
if let data = try? fetchDataFromDisk() { return data }
return nil
}
- 可以用
禁止错误传递,可以用
try!, 如果值是nil,则会抛出运行时错误
// 示例
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
指定清理行为
- 在当前代码块结束之前,可以用
defer语句执行一组语句,做任何必需的清理操作,语句的执行无关是抛出错误或者是returnbreak关键字之类 - defer 语句源代码的顺序与执行的顺序相反,即前面的后执行,后面的先执行
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// Work with the file.
}
// close(file) is called here, at the end of the scope.
}
}
- 在当前代码块结束之前,可以用
Swift从入门到精通第十四篇 - 错误处理 初识的更多相关文章
- Swift从入门到精通第十五篇 - 类型转换 初识
类型转换(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 类型转换 类型转换是检查实例类型的一种方法,或者检查来自类层级不同的父类或子类一个实例,用 is 和 as 操作符 为类 ...
- Egret入门学习日记 --- 第十四篇(书中 5.4~5.6节 内容)
第十四篇(书中 5.4~5.6节 内容) 书中内容: 总结 5.4节 内容重点: 1.如何编写自定义组件? 跟着做: 重点1:如何编写自定义组件? 文中提到了重要的两点. 好,我们来试试看. 第一步, ...
- Scala入门到精通——第二十四节 高级类型 (三)
作者:摆摆少年梦 视频地址:http://blog.csdn.net/wsscy2004/article/details/38440247 本节主要内容 Type Specialization Man ...
- Simulink仿真入门到精通(十四) Simulink自定义环境
14.1 Simulink环境自定义功能 sl_sustomization.m函数是Simulink提供给用户使用MATLAB语言自定义Simulink标准人机界面的函数机制.若sl_sustomiz ...
- Simulink仿真入门到精通(十九) 总结回顾&自我练习
从2019年12月27到2020年2月12日,学习了Simulink仿真及代码生成技术入门到精通,历时17天. 学习的比较粗糙,有一些地方还没理解透彻,全书梳理总结: Simulink的基础模块已基本 ...
- Swift从入门到精通第十一篇 - 初始化 初识
初始化(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 初始化 初始化是类.结构体.枚举生成实例的过程,为该类的每个存储属性设置初始值,有些在实例使用前的设置或初始化也可在此实现 ...
- Swift从入门到精通第八篇 - 方法 初识
方法(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 方法 结构体.枚举.类都可以定义方法(实例方法.类型方法) 实例方法(Instance Methods) 实例方法只能用实例 ...
- SpringBoot第二十四篇:应用监控之Admin
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11457867.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言 前一章(S ...
- 解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译)
解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译) http://improve.dk/how-are-vardecimals-stored/ 在这篇文章,我将深入研究 ...
随机推荐
- Throughput Controller
吞吐量控制器(Throughput Controller)介绍 作用:控制其子节点的执行次数与负载比例分配 Total Executions: 整个测试计划中的总执行次数 Percent Execut ...
- Jvm内存泄漏
内存泄漏和内存溢出的关系 内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存.即被分配的对象可达但已无用. 内存溢出:指程序运行过程中无法申请到足够的内存而导致的一 ...
- jmeter学习笔记-----第一天
环境简介:apache-jmeter-3.3 win10系统 一.Jmeter录制操作步骤: 1.工作台---添加HTTP代理服务器: 2.为自己笔记本的浏览器设置相同代理: 3.测试计划下-s ...
- Zabbix4.0安装浅谈
一.此篇文章存在意义 针对超级小白,大神绕过 在zabbix官网https://www.zabbix.com/download里,需要数据库,但是并没有指导小白的我们如何安装数据库,此文章包含了Mys ...
- tab栏切换制作
tab栏切换制作 先上图 要求1:默认状态,第一个选项卡被选中,展示第一个选项卡的内容 策略:第一个选项卡默认有被选中的样式,第一个选项卡对应的display: block,其他的dispaly设为n ...
- 打印机服务配置篇WindowsServer2008
本次配置Server2008 打印服务器 目的实现Kingdee远程打印服务,直接在金蝶客户端部署打印机服务器 服务器角色: --打印服务器 --LPD服务 --Internet打印 *打印服务 ...
- Azure Devops: COPY failed: stat /var/lib/docker/tmp/docker-builder268095359/xxxxxxx.csproj no such file or directory
在Azure Devops中部署docker镜像时, 出现COPY failed: stat /var/lib/docker/tmp/docker-builder268095359/xxxxxxx. ...
- Codeforces 814D
题意略. 思路: 由于不重合这个性质,我们可以将每一个堆叠的圆圈单独拿出来考虑,而不用去考虑其他并列在同一层的存在, 在贪心解法下,发现,被嵌套了偶数层的圆圈永远是要被减去的,而奇数层的圆圈是要加上的 ...
- 在.net core web api项目中安装swagger展示api接口(相当于生成api文档)
1, 建立或打开项目后,在“程序包管理器控制台”中执行以下命令添加包引用: Install-Package Swashbuckle.AspNetCore 2,在项目中打开Startup.cs文件,找 ...
- 百度之星初赛A轮 A 度度熊拼三角 贪心
度度熊拼三角 Accepts: 2536 Submissions: 4433 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 6553 ...