//错误处理

import UIKit

/*错误处理(Error Handling):响应错误以及从错误中恢复的过程

在 Swift 中,错误用符合ErrorType协议的类型的值来表示。这个空协议表明该类型可以用于错误处理,Swift 的枚举类型尤为适合构建一组相关的错误状态,枚举的关联值还可以提供错误状态的额外信息

抛出错误使用throw关键字,如:throw VendingMachineError.InsufficientFunds(coinsNeeded: 5)

处理错误:

1.某个错误被抛出时,附近的某部分代码必须负责处理这个错误,例如纠正这个问题、尝试另外一种方式、或是向用户报告错误

2.Swift 中有4种处理错误的方式。你可以把函数抛出的错误传递给调用此函数的代码、用do-catch语句处理错误、将错误作为可选类型处理、或者断言此错误根本不会发生

3.为了标识出会抛出错误的地方,在调用一个能抛出错误的函数、方法或者构造器之前,加上try关键字,或者try?或try!这种变体

4.用 Do-Catch 处理错误:

a.如果在do子句中的代码抛出了一个错误,这个错误会与catch子句做匹配,从而决定哪条子句能处理它。

b.如果一条catch子句没有指定匹配模式,那么这条子句可以匹配任何错误,并且把错误绑定到一个名字为error的局部常量

c.catch子句不必将do子句中的代码所抛出的每一个可能的错误都作处理,如果所有catch子句都未处理错误,错误就会传递到周围的作用域,但错误最终都要被处理。

do {

try ...

}catch ... {

...

}catch ... {

...

}

用 throws 函数传递错误:

1.为了表示一个函数、方法或构造器可以抛出错误,在函数声明的参数列表之后加上throws关键字。一个标有throws关键字的函数被称作throws函数。如果这个函数指明了返回值类型,throws关键词需要写在箭头(->)的前面。如:func canThrowErrors() throws -> String

2.一个 throws 函数可以在其内部抛出错误,并将错误传递到函数被调用时的作用域。

3.只有 throws 函数可以传递错误。任何未声明为throws的函数内部抛出的错误只能在函数内部处理!

将错误转换成可选值:

1.可以使用try?通过将错误转换成一个可选值来处理错误。如果在评估try?表达式时一个错误被抛出,那么表达式的值就是nil

func fetchData() -> Data? {

if let data = try? fetchDataFromDisk() {

return data

}

if let data = try? fetchDataFromServer() {

return data

}

return nil

}

禁用错误传递:在表达式前面写try!来禁用错误传递,这会把调用包装在一个断言不会有错误抛出的运行时断言中。如果实际上抛出了错误,你会得到一个运行时错误。

如: let photo = try! loadImage("./Resources/John Appleseed.jpg")  虽然loadImage函数为throws函数,但此处通过给定的参数调用时不会抛出错误,所以用禁用错误传递try!

指定清理操作:

1.使用defer语句在即将离开当前代码块时执行一系列语句,该语句让你能执行一些必要的清理工作,不管是以何种方式离开当前代码块的——无论是由于抛出错误而离开,还是由于诸如return或者break的语句,

2.defer语句将代码的执行延迟到当前的作用域退出之前

3.该语句由defer关键字和要被延迟执行的语句组成。延迟执行的语句不能包含任何控制转移语句,例如break或是return语句,或是抛出一个错误。延迟执行的操作会按照它们被指定时的顺序的相反顺序执行

func processFile(filename: String) throws {

if exists(filename) {

let file = open(filename)

defer {

close(file)     //defer内的语句将被延迟执行,执行多语句时反顺序执行

}

while let line = try file.readline() {

// 处理文件代码

}

//defer内的 close(file) 在这里才会被调用,即作用域的最后。

}

}

*/

//===================用枚举定义错误类型信息=====

enum VendingMachineError: ErrorType {

case InvalidSelection                    //选择无效

case InsufficientFunds(coinsNeeded: Int) //金额不足

case OutOfStock                          //缺货

}

//===================

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 dispenseSnack(snack: String) {

print("Dispensing \(snack)")

}

func vend(itemNamed name: String) throws {

//throws关键字,定义了该函数可抛出throw错误,在调用此方法的地方,必须要么直接处理这些错误,使用do-catch语句,try?或try!;要么继续将这些错误传递下去

//guard ... else{ ... } ,表达式为false时执行else,为true时跳过else的代码,执行后面的代码

guard var item = inventory[name] else {

throw VendingMachineError.InvalidSelection  //这里的throw 抛出指定错误类型到外部,通过其它方式处理该错误

}

guard item.count > 0 else {

throw VendingMachineError.OutOfStock

}

guard item.price <= coinsDeposited else {

throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited)

}

coinsDeposited -= item.price

--item.count

inventory[name] = item

dispenseSnack(name)

}

}

let favoriteSnacks = [

"Alice": "Chips",

"Bob": "Licorice",

"Eve": "Pretzels",

]

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {

let snackName = favoriteSnacks[person] ?? "Candy Bar"

//空合运算符"a ?? b",a必须为可选类型,若a有值则取值,无值则取b的值,类型必须一样

try vendingMachine.vend(itemNamed: snackName)

}

//=======do-catch=========

var vendingMachine = VendingMachine()

vendingMachine.coinsDeposited = 8

do {

try buyFavoriteSnack("Alice", vendingMachine: vendingMachine)

} 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.")

}

// 打印 “Insufficient funds. Please insert an additional 2 coins.”

swift学习笔记之-错误处理的更多相关文章

  1. 【swift学习笔记】二.页面转跳数据回传

    上一篇我们介绍了页面转跳:[swift学习笔记]一.页面转跳的条件判断和传值 这一篇说一下如何把数据回传回父页面,如下图所示,这个例子很简单,只是把传过去的数据加上了"回传"两个字 ...

  2. Swift学习笔记(一)搭配环境以及代码运行成功

    原文:Swift学习笔记(一)搭配环境以及代码运行成功 1.Swift是啥? 百度去!度娘告诉你它是苹果最新推出的编程语言,比c,c++,objc要高效简单.能够开发ios,mac相关的app哦!是苹 ...

  3. swift学习笔记5——其它部分(自动引用计数、错误处理、泛型...)

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  4. swift学习笔记4——扩展、协议

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  5. swift学习笔记2——函数、闭包

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  6. swift学习笔记1——基础部分

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  7. 记录:swift学习笔记1-2

    swift还在不断的更新做细微的调整,都说早起的鸟儿有虫吃,那么我们早点出发吧,趁着国内绝大多数的coder们还没有开始大范围普遍应用. 网上有些大神说:swift很简单!我不同意这个观点,假如你用h ...

  8. swift学习笔记3——类、结构体、枚举

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  9. Swift学习笔记一

    最近计划把Swift语言系统学习一下,然后将MagViewer用这种新语言重构一次,并且优化一下,这里记录一下Swift的学习笔记. Swift和Objective-C相比,在语法和书写形式上做了很多 ...

随机推荐

  1. 安卓开发笔记——自定义广告轮播Banner(实现无限循环)

    关于广告轮播,大家肯定不会陌生,它在现手机市场各大APP出现的频率极高,它的优点在于"不占屏",可以仅用小小的固定空位来展示几个甚至几十个广告条,而且动态效果很好,具有很好的用户& ...

  2. WebKit内核分析之FrameLoader

    参考地址:http://blog.csdn.net/dlmu2001/article/details/6168545 FrameLoader类负责一个Frame的加载,在Frame的流程中起到非常重要 ...

  3. nginx rewrite重写与防盗链配置

    nginx rewrite重写规则与防盗链配置方法 时间:2016-02-04 15:16:58来源:网络 导读:nginx rewrite重写规则与防盗链配置方法,rewrite规则格式中flag标 ...

  4. 【转载】 IE/Firefox每次刷新时自动检查网页更新,无需手动清空缓存的设置方法

    [参考了别人的文章]我们做技术,经常在写页面的时候需要多次刷新测试,可是浏览器都有自己的 缓存机制,一般CSS和图片都会被缓存在本地,这样我们修改的CSS就看不到效果 了,每次都去清空缓存,再刷新看效 ...

  5. 快速开发~Rafy框架的初步认识

    当我们开始使用EF的同时,是不是就会更好的认识了其他的ORM框架,最近接触了Rafy的使用,感觉还是蛮有兴趣去学习的,虽然最初的我到现在看的并不深入,但是我个人感觉还是可以简单地做一些总结的啦,或许语 ...

  6. 写的一个Sass 和Compass的例子

    /*1.打开项目根目录下的 config.rb 文件 2.搜索 line_comments 关键词,默认应该是 # line_comments = false 3.去掉前面的 #,保存 config. ...

  7. ES6入门系列一(基础)

    1.let命令 Tips: 块级作用域(只在当前块中有效) 不会变量提升(必须先申明在使用) 让变量独占该块,不再受外部影响 不允许重复声明 总之:let更像我们熟知的静态语言的的变量声明指令 ES6 ...

  8. Eclipse中使用Junit编写测试用例

    Eclipse自带Junit插件,不用安装就能在项目中编写测试用例,非常方便. 在项目中添加Junit库 在编写测试用例之前,需要先引入Junit.对项目根目录右键,选择Properties,Java ...

  9. Socket.IO 1.0 正式发布,快速可靠的实时引擎

    Socket.IO 是目前 Web 领域最火的实时引擎,用于实现基于事件的双向实时的通信.它适用于任何平台,浏览器或设备,专注于可靠性和速度.您可以将数据推送到客户端,并获得实时的计数,日志或图表. ...

  10. Android学习笔记之图片轮播...

    PS:一个bug又折腾了一个下午....哎... 学习内容: 1.Android利用ViewPager和PagerAdapter实现图片轮播... 2.使用反射机制获取Android的资源信息... ...