Swift 错误处理
2016-02-09 16:07
393 查看
主要内容:
如何使用
如何表示错误
如何使用
一.Swift 2.0之前的错误处理
错误处理是应用中响应错误与从错误中恢复的过程。在Swift 2.0之前,错误报告与Objective-C的模式相同,但是Swift可以使用可选类型的返回值,返回
最简单的错误处理,函数的返回值会表明函数执行是否成功:返回值可以是布尔值
尽管可以以这种方式处理错误,能够调整来满足大多数的需求,但是它一定不是最好的方案。这种方案有一些问题,最大的问题是开发者容易忽略函数返回值和错误自身。大多数有经验的开发者对于检查错误很小心,但是初学者很难理解,特别是函数没有包含
除了使用
尽管使用
二.Swift 2中的错误处理
《一.表示错误
在理解Swift中错误处理的工作原理前,必须要明白如何表示错误。在Swift中,错误是由遵守
我们来看一下如何使用枚举来表示错误,首先,定义一个名字为
在这个例子中,定义了遵守
三.捕获错误
当函数抛出错误时,我们需要在调用该函数的代码中捕获它。使用
如果错误被抛出,它会一直往外传递,直到被
上述例子中,
在
如果想要获取错误,可以使用
使用
我们也可以让错误传递出去,而不是立即捕获它们。为了实现这样的目的,只需要在函数定义中添加
如果我们确定错误不会被抛出,可以使用强制try(
因为
如果需要执行一些清理工作,而不管是否有一些错误,可以使用
如果调用这个函数,打印到控制台的第一行是
Swift使用
使用
我们也可以限制对函数或类型的获取,之前
为了使用
如何使用
do-catch块
如何表示错误
如何使用
availability属性
一.Swift 2.0之前的错误处理
错误处理是应用中响应错误与从错误中恢复的过程。在Swift 2.0之前,错误报告与Objective-C的模式相同,但是Swift可以使用可选类型的返回值,返回
nil表示函数内部发生了错误。
最简单的错误处理,函数的返回值会表明函数执行是否成功:返回值可以是布尔值
true/false,或者枚举
enum,如果函数没有成功执行的话,该值可以表明哪里发生了错误。如果需要报告关于错误的额外信息,我们可以添加
NSErrorPointer类型的
NSError参数,但这不是最简单的途径,这些错误往往会被开发者忽略。下面的例子展示了Swift 2.0之前如何处理错误的:
var str = "Hello World" var error: NSError var results = str.writeToFile(path,atomically: true,encoding:NSUTF8StringEncoding,error: &error) if results { // } else { println("Error writing filer: \(error)") }
尽管可以以这种方式处理错误,能够调整来满足大多数的需求,但是它一定不是最好的方案。这种方案有一些问题,最大的问题是开发者容易忽略函数返回值和错误自身。大多数有经验的开发者对于检查错误很小心,但是初学者很难理解,特别是函数没有包含
NSError参数时。
除了使用
NSError,我们也可以使用
NSException类来抛出与捕获异常。但是,很少的开发者使用这种方法,甚至在Cocoa与Cocoa Touch框架中,这种处理异常的方法也很少被使用。
尽管使用
NSError类与返回值来处理错误奏效,但是很多人,对于Apple刚开始发布Swift时没有包含额外的错误处理很失望。现在,Swift 2.0,我们拥有原生的错误处理。
二.Swift 2中的错误处理
《一.表示错误
在理解Swift中错误处理的工作原理前,必须要明白如何表示错误。在Swift中,错误是由遵守
ErrorType协议的类型的值表示的。枚举非常适合作为错误情况的模型,因为通常我们有有限数量的错误情况来表示。
我们来看一下如何使用枚举来表示错误,首先,定义一个名字为
MyError的错误,该错误有三种错误情况:
Minor、
Bad、
Terrible。
enum MyError: ErrorType { case Minor case Bad case Terrible }
在这个例子中,定义了遵守
ErrorType协议的
MyError枚举,然后定义了三中错误情况。我们也可以对错误情况使用相关值
associated values。为其中一个错误情况添加描述:
enum MyError: ErrorType { case Minor case Bad case Terrible (description: String) }
三.捕获错误
当函数抛出错误时,我们需要在调用该函数的代码中捕获它。使用
do-catch代码块来完成,语法如下:
do { try 调用会抛出错误的函数 ... } catch [pattern] { ... }
如果错误被抛出,它会一直往外传递,直到被
catch处理。其中,
catch后面跟上匹配错误的模式(
a pattern to match the error)
import Cocoa let maxNumber = 100 let minNumber = 8 enum PlayerNumberError: ErrorType { case NumberTooHigh(description: String) case NumberTooLow(description: String) case NumberAlreadyAssigned case NumberDoesNotExist } typealias BaseballPlayer = (firstName: String,lastName: String,number: Int) struct BaseballTeam { var players: [Int: BaseballPlayer] = [ : ] mutating func addPlayer(player: BaseballPlayer) throws { guard player.number < maxNumber else { throw PlayerNumberError.NumberTooHigh(description: "Max number is \(maxNumber)") } guard player.number > minNumber else { throw PlayerNumberError.NumberTooLow(description: "Min number is \(minNumber)") } guard players[player.number] == nil else { throw PlayerNumberError.NumberAlreadyAssigned } players[player.number] = player } func getPlayerByNumber(number: Int) throws -> BaseballPlayer { if let player = players[number] { return player } else { throw PlayerNumberError.NumberDoesNotExist } } } var myTeam = BaseballTeam(players: [ : ]) do { let player = try myTeam.getPlayerByNumber(8) print("Player is \(player.firstName) \(player.lastName)") } catch PlayerNumberError.NumberDoesNotExist { print("No player has that number") }
上述例子中,
do-catch块中调用了
getPlayerByNumber()方法,如果队中没有成员分配该数字,则该方法会抛出
PlayerNumberError.NumberDoesNotExist错误情况。因此,我们在
catch表达式中匹配那个错误。
在
catch后面不必包含一个模式,如果
catch后面没有包含一个模式,或者放置一个下划线,
catch表达式会匹配所有的错误情况。例如,下面任何一个
catch表达式都会捕获所有的错误:
do { } catch { }
do { } catch _ { }
如果想要获取错误,可以使用
let关键字,如下:
do { } catch let error { }
使用
catch表达式来捕获不同的错误情况:
do { try myTeam.addPlayer(("David","Ortiz",10)) } catch PlayerNumberError.NumberTooHigh(let description) { print("Error: \(description)") } catch PlayerNumberError.NumberTooLow(let description) { print("Error: \(description)") } catch PlayerNumberError.NumberAlreadyAssigned { print("Error: Number already assigned") }
我们也可以让错误传递出去,而不是立即捕获它们。为了实现这样的目的,只需要在函数定义中添加
throws关键字。例如下面的例子中,将错误传递到调用该函数的代码中,而不是在函数中处理错误。
func myFunc() throws { try myTeam.addPlayer(("David","Ortiz",34)) }
如果我们确定错误不会被抛出,可以使用强制try(
forced-try)表达式来调用函数,写法是
try!。强制try表达式阻止错误传递,会将函数调用包装在运行时断言中,这样调用就不会抛出错误。如果抛出了错误,就会得到运行时错误,所以使用这种表达式时要注意。
try?关键字尝试执行可能会抛出错误的操作。如果操作成功,会返回可选类型的结果。但是如果操作失败,抛出错误,会返回nil,错误会被丢弃。
因为
try?关键字返回的结果是可选类型,通常将其与可选类型绑定结合,如下:
if let player = try? myTeam.getPlayerByNumber(34) { print("Player is \(player.firstName)") }
如果需要执行一些清理工作,而不管是否有一些错误,可以使用
defer。使用
defer来在代码执行刚离开当前作用域前执行代码块,如下:
func deferFunction() { print("Function started") var str: String? defer { print("In defer block") if let s = str { print("str is \(s)") } } str = "John" print("Function finished") }
如果调用这个函数,打印到控制台的第一行是
Function started,代码的执行会跳过
defer块,接着
Function finished会打印到控制台。最后,离开函数域前,
defer块会执行。执行的结果如下:
Function started Function finished In defer block str is John
availability
属性
Swift使用availability属性来安全地包装代码,只有在正确版本的操作系统可获得时,该代码才会运行。有两种方式来使用
availability属性,第一种方式允许我们执行特定的代码块,与
if或
guard一同工作。第二种方式允许我们将一个方法或类型标记为只在特定平台上可获得。
availability属性可接受五个用逗号隔开的参数,允许我们定义执行代码所需要的操作系统与应用扩展的最低版本。这些参数包括:
iOS:兼容代码的最低iOS版本
OSX:兼容代码的最低OS X版本
watchOS:兼容代码的最低watchOS版本
iOSApplicationExtension:兼容代码的最低iOS应用kuoz
OSXApplicationExtension:兼容代码的最低OS X应用扩展
使用
*来结束参数列表,我们来看一下如何只有在满足最小要求时才执行特定的代码块:
if #available(iOS 9.0,OSX 10.10,watchOS 2 ,*) { print("Minimum requirements met") } else { print("Minimum requirements not met") }
我们也可以限制对函数或类型的获取,之前
availability的前缀是
#,为了限制对函数或类型的获取,使用
@作为前缀。
@available(iOS 9.0,*) func testAvailability() { } @available(iOS 9.0,*) struct TestStruct { }
为了使用
@available属性来限制对函数与类型的获取,必须要使用
#available将调用该函数与类型的代码进行包装。
if #available(iOS 9.0,*) { testAvailability() } else { }
相关文章推荐
- Swift基础语法学习总结二
- Swift基础语法学习总结一
- Project Perfect让Swift在服务器端跑起来-引言(一)
- Swift快速入门(三)运算符
- swift学习笔记之-继承
- swift学习笔记之-闭包
- swift学习笔记之-下标脚本
- swift学习笔记之-枚举
- Swift快速入门(三)运算符
- 12.Swift 中的关键字详解
- 苹果新的编程语言 Swift 语言进阶(六)--函数和闭包
- swift算法手记-9
- Swift 官方文档地址
- swift学习笔记之-函数
- Swift中使用typealias定义一个闭包closure
- XCGLogger Swift日志打印
- UIColor之扩展Swift
- Swift 教學:如何使用iOS Charts API 製作漂亮的圖表
- swift如何实现语言国际化,适应各国语言
- swift 通知