错误处理(学习笔记)

环境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? 表达式的值为 nil
        func 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 语句执行一组语句,做任何必需的清理操作,语句的执行无关是抛出错误或者是 return break 关键字之类
    • 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从入门到精通第十四篇 - 错误处理 初识的更多相关文章

  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. (二十九)c#Winform自定义控件-文本框(二)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  2. 【RabbitMQ】如何进行消息可靠投递【上篇】

    说明 前几天,突然发生线上报警,钉钉连发了好几条消息,一看是RabbitMQ相关的消息,心头一紧,难道翻车了? [橙色报警] 应用[xxx]在[08-15 16:36:04]发生[错误日志异常],al ...

  3. Scrapy爬虫框架学习

    一.Scrapy框架简介 1. 下载页面 2. 解析 3. 并发 4. 深度 二.安装 linux下安装 pip3 install scrapy windows下安装 a.pip3 install w ...

  4. 初学html总结

    2019-08-17 17:58:49 html:超文本标记语言,用于网页结构的搭建 html语言构成:由标签.属性.属性值构成 标签:" < "后面第一个单词 属性:标签后 ...

  5. poj3415_Common Substrings

    题意 给定两个字符串,求长度大于等于k的公共子串数. 分析 将两个字符串中间加个特殊字符拼接,跑后缀数组. 将题目转化为对每一个后缀求\(\sum_{j=1}^{i-1}lcp(i,j)\),且后缀\ ...

  6. 关于《Selenium3自动化测试实战--基于python语言》

    2016年1月,机缘巧合下我出版了<Selenium2自动化测试实战--基于python语言>这本书,当时写书的原因是,大部分讲Selenium的书并不讲编程语言和单元测试框,如果想在项目 ...

  7. JS实现停留几秒sleep,Js中for循环的阻塞机制,setTimeout延迟执行

    //第一种,使用while循环 function sleep(delay) { var start = (new Date()).getTime(); while((new Date()).getTi ...

  8. Python机器学习笔记:不得不了解的机器学习知识点(2)

    之前一篇笔记: Python机器学习笔记:不得不了解的机器学习知识点(1) 1,什么样的资料集不适合用深度学习? 数据集太小,数据样本不足时,深度学习相对其它机器学习算法,没有明显优势. 数据集没有局 ...

  9. Python基础 2-2 列表的实际应用场景

    引言 本章主要介绍列表在实际应用中的使用场景,多维列表(嵌套列表) 如果你需要在列表保存每个人员的一些基本信息,使用列表嵌套来保存这种信息是个不错的主意. 多维列表 列表可以根据实际情况嵌套使用,比如 ...

  10. C#开发学习人工智能的第一步

    前言 作为一个软件开发者,我们除了要学会复制,黏贴,还要学会调用API和优秀的开源类库. 也许,有人说C#做不了人工智能,如果你相信了,那只能说明你的思想还是狭隘的. 做不了人工智能的不是C#这种语言 ...