错误处理(学习笔记)

环境Xcode 11.0 beta4 swift 5.1

  • 错误表现和抛出

    • swift 中,错误由符合 Error 协议的类型值表示
      1. // 示例
      2. enum VendingMachineError: Error {
      3. case invalidSelection
      4. case insufficientFunds(coinsNeeded: Int)
      5. case outOfStock
      6. }
      7. // 抛出错误
      8. throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
  • 错误处理

    • 在 Swift 中有四种处理错误的方式:一、从函数中把错误传递出来;二、用 do-catch 语句;三、作为可选值处理;四、用断言

    • 在 Swift 中错误处理与其它语言(包括OC)的异常类似,Swift 中错误处理不会涉及展开堆栈的调用,而堆栈的调用消耗是很大的,从性能的角度出发 throw 语句的性能与 return 性能是一样的

    • 函数抛出错误,只有声明了 throws 的函数才能往外抛出错误,如果不是则抛出的错误必须在函数内部处理

      1. func canThrowErrors() throws -> String
      2. //
      3. func cannotThrowErrors() -> String
    • 示例代码

      1. struct Item {
      2. var price: Int
      3. var count: Int
      4. }
      5. //
      6. class VendingMachine {
      7. var inventory = [
      8. "Candy Bar": Item(price: 12, count: 7),
      9. "Chips": Item(price: 10, count: 4),
      10. "Pretzels": Item(price: 7, count: 11)
      11. ]
      12. var coinsDeposited = 0
      13. //
      14. func vend(itemNamed name: String) throws {
      15. guard let item = inventory[name] else {
      16. throw VendingMachineError.invalidSelection
      17. }
      18. //
      19. guard item.count > 0 else {
      20. throw VendingMachineError.outOfStock
      21. }
      22. //
      23. guard item.price <= coinsDeposited else {
      24. throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
      25. }
      26. //
      27. coinsDeposited -= item.price
      28. //
      29. var newItem = item
      30. newItem.count -= 1
      31. inventory[name] = newItem
      32. //
      33. print("Dispensing \(name)")
      34. }
      35. }
      36. let favoriteSnacks = [
      37. "Alice": "Chips",
      38. "Bob": "Licorice",
      39. "Eve": "Pretzels",
      40. ]
      41. func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
      42. let snackName = favoriteSnacks[person] ?? "Candy Bar"
      43. try vendingMachine.vend(itemNamed: snackName) // 如果这里有错误,将会向外层抛
      44. }
    • 可抛出的初始化器也可以向外抛出错误

      1. struct PurchasedSnack {
      2. let name: String
      3. init(name: String, vendingMachine: VendingMachine) throws {
      4. try vendingMachine.vend(itemNamed: name)
      5. self.name = name
      6. }
      7. }
    • do-catch 处理错误,一般格式如下

      1. do {
      2. try expression
      3. // statements
      4. } catch pattern1 {
      5. // statements
      6. } catch pattern2 where condition {
      7. // statements
      8. } catch {
      9. // statements
      10. }
      11. // catch 后的 pattern1 表示这个大括号内处理 pattern1 类型的错误,如果省略不写表示处理任何类型的错误且把错误绑定到一个常量 `error`
      1. var vendingMachine = VendingMachine()
      2. vendingMachine.coinsDeposited = 8
      3. do {
      4. try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
      5. print("Success! Yum.")
      6. } catch VendingMachineError.invalidSelection {
      7. print("Invalid Selection.")
      8. } catch VendingMachineError.outOfStock {
      9. print("Out of Stock.")
      10. } catch VendingMachineError.insufficientFunds(let coinsNeeded) {
      11. print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
      12. } catch {
      13. print("Unexpected error: \(error).")
      14. }
      15. // Prints "Insufficient funds. Please insert an additional 2 coins."
    • 将错误转换为可选值

      • 可以用 try? 将错误转换为可选值,如果有错误抛出,计算 try? 表达式的值为 nil
        1. func someThrowingFunction() throws -> Int {
        2. // ....
        3. }
        4. let x = try? someThrowingFunction()
        5. let y: Int?
        6. do {
        7. y = try someThrowingFunction()
        8. }catch {
        9. y = nil
        10. }
        11. // 如果函数 someThrowingFunction 抛出错误,则 x 的值为 nil;否则 x、y 就是函数返回的值,且此时x、y是可选值
      • 如果想用 try? 准确处理所有错误,如下示例
        1. func fetchData() -> Data? {
        2. if let data = try? fecthDataFromDisk() { return data }
        3. if let data = try? fetchDataFromDisk() { return data }
        4. return nil
        5. }
    • 禁止错误传递,可以用 try! , 如果值是 nil,则会抛出运行时错误

    1. // 示例
    2. let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
  • 指定清理行为

    • 在当前代码块结束之前,可以用 defer 语句执行一组语句,做任何必需的清理操作,语句的执行无关是抛出错误或者是 return break 关键字之类
    • defer 语句源代码的顺序与执行的顺序相反,即前面的后执行,后面的先执行
      1. func processFile(filename: String) throws {
      2. if exists(filename) {
      3. let file = open(filename)
      4. defer {
      5. close(file)
      6. }
      7. while let line = try file.readline() {
      8. // Work with the file.
      9. }
      10. // close(file) is called here, at the end of the scope.
      11. }
      12. }

Swift从入门到精通第十四篇 - 错误处理 初识的更多相关文章

  1. Swift从入门到精通第十五篇 - 类型转换 初识

    类型转换(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 类型转换 类型转换是检查实例类型的一种方法,或者检查来自类层级不同的父类或子类一个实例,用 is 和 as 操作符 为类 ...

  2. Egret入门学习日记 --- 第十四篇(书中 5.4~5.6节 内容)

    第十四篇(书中 5.4~5.6节 内容) 书中内容: 总结 5.4节 内容重点: 1.如何编写自定义组件? 跟着做: 重点1:如何编写自定义组件? 文中提到了重要的两点. 好,我们来试试看. 第一步, ...

  3. Scala入门到精通——第二十四节 高级类型 (三)

    作者:摆摆少年梦 视频地址:http://blog.csdn.net/wsscy2004/article/details/38440247 本节主要内容 Type Specialization Man ...

  4. Simulink仿真入门到精通(十四) Simulink自定义环境

    14.1 Simulink环境自定义功能 sl_sustomization.m函数是Simulink提供给用户使用MATLAB语言自定义Simulink标准人机界面的函数机制.若sl_sustomiz ...

  5. Simulink仿真入门到精通(十九) 总结回顾&自我练习

    从2019年12月27到2020年2月12日,学习了Simulink仿真及代码生成技术入门到精通,历时17天. 学习的比较粗糙,有一些地方还没理解透彻,全书梳理总结: Simulink的基础模块已基本 ...

  6. Swift从入门到精通第十一篇 - 初始化 初识

    初始化(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 初始化 初始化是类.结构体.枚举生成实例的过程,为该类的每个存储属性设置初始值,有些在实例使用前的设置或初始化也可在此实现 ...

  7. Swift从入门到精通第八篇 - 方法 初识

    方法(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 方法 结构体.枚举.类都可以定义方法(实例方法.类型方法) 实例方法(Instance Methods) 实例方法只能用实例 ...

  8. SpringBoot第二十四篇:应用监控之Admin

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11457867.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   前一章(S ...

  9. 解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译)

    解剖SQLSERVER 第十四篇    Vardecimals 存储格式揭秘(译) http://improve.dk/how-are-vardecimals-stored/ 在这篇文章,我将深入研究 ...

随机推荐

  1. 【JS档案揭秘】第二集 Event loop与执行栈

    我时常在思考关于JS的很多知识在工作中有什么用?是否只能存在于面试这种理论性的东西中,对于我们的业务和工作,它们又能扮演怎样的角色.以后在JS档案揭秘的每一期里,都会加入我对于业务的思考,让这些知识不 ...

  2. Unity进阶之ET网络游戏开发框架 04-资源打包

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  3. 03 requests模块基础

    1. requests 模块简介 什么是requests 模块 requests模块是python中原生的基于网络请求的模块,功能强大,用法简洁高效.在爬虫领域中占据着半壁江山的地位.requests ...

  4. rocketMQ部署

    rocketMQ部署(单机) 1.          环境: CentOS7 64  &  JDK1.8+ 64  & 用户:www 2.          下载binary文件包: ...

  5. 一句道破所有的springmvc(面试必备)

    springmvc流程 : URL--------前端控制器DispatcherServlet---------HandlerMapping处理器映射器-------调用HandlerAdapter处 ...

  6. 图灵学院Java架构师-VIP-【性能调优-Mysql索引数据结构详解与索引优化】

    最近报名了图灵学院的架构专题的付费课程,没有赶上6月份开课,中途加入的.错过了多线程的直播课程,只能看录播了

  7. 谷歌移动UI框架Flutter教程之Widget

    引言 在之间我已经介绍了关于Flutter的下载安装以及配置,还有开发工具Android Studio的配置,还不知道的同学可以看看我这篇博客--谷歌移动UI框架Flutter入门.这里为什么非要用A ...

  8. Linux系统启动流程(重要!)

    Linux系统启动流程   从上至下为: BIOS  MBR:Boot Code 执行引导程序-GRUB(操作系统) 加载内核 执行init run level 1.BIOS(Basic Input ...

  9. input 上传图片

    <!--多图上传--><input name="image_mortgage_property[]" type="file" multiple ...

  10. Mac os 下 python爬虫相关的库和软件的安装

      由于最近正在放暑假,所以就自己开始学习python中有关爬虫的技术,因为发现其中需要安装许多库与软件所以就在这里记录一下以避免大家在安装时遇到一些不必要的坑. 一. 相关软件的安装:   1. h ...