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/ 在这篇文章,我将深入研究 ...
随机推荐
- linux之用户和用户组管理详解
#############用户和用户组管理###################linux只认识UID和GID #可在/etc/passwd 和/etc/group中找到 ##/etc/passwd ...
- 使用pandoc简单教程
使用pandoc作为过滤器 {#step-4-using-pandoc-as-a-filter} 类型 pandoc 并按Enter键.你应该看到光标就在那里,等着你输入一些东西.输入: Hello ...
- Day 01--选题与设计(一)
1.第一天我们主要确定了软件课设的项目,做一个学校内食堂订送餐的微信小程序.我们大体的设计思路是:可以实现学生身份的认证,幷使学生们能自行选择校园内的食堂,挑选各个食堂各个窗口菜谱上可以选择的菜,选择 ...
- Python模块之pexpect
一.pexpect模块介绍 Pexpect使Python成为控制其他应用程序的更好工具.可以理解为Linux下的expect的Python封装,通过pexpect我们可以实现对ssh,ftp,pass ...
- 多线程与高并发(五) Lock
之前学习了如何使用synchronized关键字来实现同步访问,Java SE 5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功 ...
- springboot中的外界jar的引入:
<!-- 小米推送jar配置Start --> <dependency> <groupId>com.xiao.mi.push</groupId> < ...
- Nginx介绍与反向代理
Nginx的产生 没有听过Nginx?那么一定听过它的"同行"Apache吧!Nginx同Apache一样都是一种WEB服务器.基于REST架构风格,以统一资源描述符(Unifor ...
- Javaweb MVC设计模式
Javaweb MVC设计模式 一.Java EE开发流程 二.MVC设计模式 什么是MVC? MVC是Model-View-Controller的简称,即模型-视图-控制器. MVC是一种设计模式, ...
- 【原创】Linux cpufreq framework
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- Oracle - SQL语句实现数据库快速检索
SQL语句实现数据库快速检索 有时候在数据库Debug过程中,需要快速查找某个关键字. 1:使用PLSQL Dev自带的查找数据库对象,进行对象查找 缺点:查找慢.耗时. 2:使用SQL语句对数据库对 ...