错误处理(学习笔记)

环境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. 安全测试基础2-sqlmap演练

    sqlmap简介 sqlmap是一个开源的渗透测试工具,可以用来进行自动化检测,利用SQL注入漏洞,获取数据库服务器的权限. 它具有功能强大的检测引擎,针对各种不同类型数据库的渗透测试的功能选项,包括 ...

  2. 为什么说java是只有值传递?

    如果你学的第一门程序语言是java可能对这个传递方式没有那么敏感,如果学了c或c++,然后再学java,那么可能对这个问题会感到困惑. 1.值传递与引用传递的概念 在将传递方式之前先理解一下形参与实参 ...

  3. 如何彻底禁用 werfalut.exe

    在程序中调用 控制台程序 的时候,一旦出现控制台出现 crash 往往会弹出 werfault 窗口, 这样往往会锁死线程,导致程序无法继续运行. 那如何禁止 werfault 窗口的弹出呢? 在 s ...

  4. 云片RocketMQ实战:Stargate的前世今生

    RocketMQ消息队列,专业消息中间件,既可为分布式应用系统提供异步解耦和削峰填谷的能力,同时也具备互联网应用所需的海量消息堆积.高吞吐.可靠重试等特性,是应对企业业务峰值时刻必备的技术. 云片由于 ...

  5. Apache性能测试工具ab使用详解~转载

    Apache自带性能测试工具ab使用详解 一. Apache的下载 1. http://www.apache.org/,进入Apache的官网 2. 将页面拖到最下方“Apache Project L ...

  6. 《NVM-Express-1_4-2019.06.10-Ratified》学习笔记(8)

    8 Feature(特性) 8.1 固件升级过程 固件升级通过重启激活的过程是: 1. 主机发一个Firmware Image Download命令,下载固件映像版本到controller.可能有多个 ...

  7. 深入浅出TypeScript(1)

    前言 在学习TypeScript过程中,我也是遇到了很多的阻力,因为并未有太多深入挖掘的场景,之前做IONIC的时候,也只是用TS,现如今,这一个系列也是记录自己学习和收获,同时希望自己的这系列教程对 ...

  8. WebSocket实现数据库更新前台实时显示

    通过一个小实例来实现数据库更新后,推送消息给前台,让前台进行相应操作. 需求 数据库更新之后服务器推送消息给前台,让前台做操作.(数据库的数据不是由服务器写入的) 实现的话说到底都是用轮询,因为数据库 ...

  9. CentOS -- RocketMQ HA & Monitoring

    RocketMQ Architecture NameServer Cluster Name Servers provide lightweight service discovery and rout ...

  10. three.js实现球体地球2018年全球GDP前十国家标记

    概况如下: 1.SphereGeometry实现自转的地球: 2.THREE.Math.degToRad,Math.sin,Math.cos实现地图经纬度与三位坐标x,y,z之间的转换: 3.Imag ...