
主要内容:
如何使用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: NSErrorvar results = str.writetofile(path,atomically: true,enCoding:NSUTF8StringEnCoding,error: &error)if results { //} else { println("Error writing filer: \(error)")}@H_419_52@尽管可以以这种方式处理错误,能够调整来满足大多数的需求,但是它一定不是最好的方案。这种方案有一些问题,最大的问题是开发者容易忽略函数返回值和错误自身。大多数有经验的开发者对于检查错误很小心,但是初学者很难理解,特别是函数没有包含
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}@H_419_52@在这个例子中,定义了遵守
ErrorType协议的MyError枚举,然后定义了三中错误情况。我们也可以对错误情况使用相关值associated values。为其中一个错误情况添加描述:enum MyError: ErrorType { case Minor case Bad case Terrible (description: String)}@H_419_52@三.捕获错误
当函数抛出错误时,我们需要在调用该函数的代码中捕获它。使用
do-catch代码块来完成,语法如下:do { try 调用会抛出错误的函数 ...} catch [pattern] { ...}@H_419_52@如果错误被抛出,它会一直往外传递,直到被
catch处理。其中,catch后面跟上匹配错误的模式(a pattern to match the error)import Cocoalet maxnumber = 100let minNumber = 8enum 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")}@H_419_52@上述例子中,
do-catch块中调用了getPlayerByNumber()方法,如果队中没有成员分配该数字,则该方法会抛出PlayerNumberError.NumberDoesNotExist错误情况。因此,我们在catch表达式中匹配那个错误。在
catch后面不必包含一个模式,如果catch后面没有包含一个模式,或者放置一个下划线,catch表达式会匹配所有的错误情况。例如,下面任何一个catch表达式都会捕获所有的错误:do { } catch { }@H_419_52@do { } catch _ { }@H_419_52@如果想要获取错误,可以使用
let关键字,如下:do {} catch let error {}@H_419_52@使用
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")}@H_419_52@我们也可以让错误传递出去,而不是立即捕获它们。为了实现这样的目的,只需要在函数定义中添加
throws关键字。例如下面的例子中,将错误传递到调用该函数的代码中,而不是在函数中处理错误。func myFunc() throws { try myTeam.addplayer(("DavID",34))}@H_419_52@如果我们确定错误不会被抛出,可以使用强制try(
forced-try)表达式来调用函数,写法是try!。强制try表达式阻止错误传递,会将函数调用包装在运行时断言中,这样调用就不会抛出错误。如果抛出了错误,就会得到运行时错误,所以使用这种表达式时要注意。
try?关键字尝试执行可能会抛出错误的 *** 作。如果 *** 作成功,会返回可选类型的结果。但是如果 *** 作失败,抛出错误,会返回nil,错误会被丢弃。因为
try?关键字返回的结果是可选类型,通常将其与可选类型绑定结合,如下:if let player = try? myTeam.getPlayerByNumber(34) { print("Player is \(player.firstname)")}@H_419_52@如果需要执行一些清理工作,而不管是否有一些错误,可以使用
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")}@H_419_52@如果调用这个函数,打印到控制台的第一行是
Function started,代码的执行会跳过defer块,接着Function finished会打印到控制台。最后,离开函数域前,defer块会执行。执行的结果如下:Function startedFunction finishedIn defer blockstr is John@H_419_52@availability属性Swift使用
availability属性来安全地包装代码,只有在正确版本的 *** 作系统可获得时,该代码才会运行。有两种方式来使用availability属性,第一种方式允许我们执行特定的代码块,与if或guard一同工作。第二种方式允许我们将一个方法或类型标记为只在特定平台上可获得。
availability属性可接受五个用逗号隔开的参数,允许我们定义执行代码所需要的 *** 作系统与应用扩展的最低版本。这些参数包括:iOS:兼容代码的最低iOS版本OSX:兼容代码的最低OS X版本watchOS:兼容代码的最低watchOS版本iOSApplicationExtension:兼容代码的最低iOS应用kuozOSXApplicationExtension:兼容代码的最低OS X应用扩展使用
*来结束参数列表,我们来看一下如何只有在满足最小要求时才执行特定的代码块:if #available(iOS 9.0,OSX 10.10,watchOS 2,*) { print("Minimum requirements met")} else { print("Minimum requirements not met")}@H_419_52@我们也可以限制对函数或类型的获取,之前
availability的前缀是#,为了限制对函数或类型的获取,使用@作为前缀。@available(iOS 9.0,*) func testAvailability() {}@available(iOS 9.0,*) struct TestStruct {}@H_419_52@为了使用
@available属性来限制对函数与类型的获取,必须要使用#available将调用该函数与类型的代码进行包装。if #available(iOS 9.0,*) { testAvailability()} else {}@H_419_52@ 总结以上是内存溢出为你收集整理的Swift 错误处理全部内容,希望文章能够帮你解决Swift 错误处理所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)