我对 Swift 的了解并不多,但我注意到的一件事是没有例外。那么他们如何在 Swift 中进行错误处理呢?有没有人发现任何与错误处理有关的东西?
Swift 2 中的情况发生了一些变化,因为有一个新的错误处理机制,它有点类似于异常,但在细节上有所不同。
如果函数/方法想要表明它可能会抛出错误,它应该包含throws这样的关键字
throws
func summonDefaultDragon() throws -> Dragon
注意:函数实际上可以抛出的错误类型没有规范。 这个声明只是声明函数可以抛出任何实现 ErrorType 类型的实例,或者根本不抛出。
为了调用函数,你需要使用 try 关键字,像这样
try summonDefaultDragon()
这条线通常应该像这样存在 do-catch 块
do { let dragon = try summonDefaultDragon() } catch DragonError.dragonIsMissing { // Some specific-case error-handling } catch DragonError.notEnoughMana(let manaRequired) { // Other specific-case error-handlng } catch { // Catch all error-handling }
注意:catch 子句使用了 Swift 模式匹配的所有强大功能,因此您在这里非常灵活。
throws如果您从本身标有关键字的函数调用抛出函数,则您可能决定传播错误:
func fulfill(quest: Quest) throws { let dragon = try summonDefaultDragon() quest.ride(dragon) }
或者,您可以使用以下方法调用 throwing 函数try?:
try?
let dragonOrNil = try? summonDefaultDragon()
这样,如果发生任何错误,您要么得到返回值,要么得到 nil。使用这种方式你不会得到错误对象。
这意味着您还可以结合try?有用的语句,例如:
if let dragon = try? summonDefaultDragon()
或者
guard let dragon = try? summonDefaultDragon() else { ... }
最后,您可以确定您知道错误实际上不会发生(例如,因为您已经检查了先决条件)并使用try!关键字:
try!
let dragon = try! summonDefaultDragon()
如果函数确实抛出错误,那么您将在应用程序中收到运行时错误,并且应用程序将终止。
为了抛出错误,您可以使用 throw 关键字这样
throw DragonError.dragonIsMissing
你可以抛出任何符合ErrorType协议的东西。对于初学者NSError,符合此协议,但您可能希望使用基于枚举的方法ErrorType,它使您能够对多个相关错误进行分组,可能还有额外的数据,像这样
ErrorType
NSError
enum DragonError: ErrorType { case dragonIsMissing case notEnoughMana(requiredMana: Int) ... }
新的 Swift 2 和 3 错误机制与 Java/C#/C++ 样式异常的主要区别如下:
do-catch
try``defer``try-catch-finally
false``Bool``nil``AnyObject``NSErrorPointer
作为简化错误处理的额外语法糖,还有两个概念
defer
guard
运行时错误:
正如 Leandros 建议的处理运行时错误(如网络连接问题、解析数据、打开文件等),您应该NSError像在 ObjC 中那样使用,因为 Foundation、AppKit、UIKit 等以这种方式报告它们的错误。所以它更多的是框架而不是语言。
另一个常用的模式是分隔成功/失败块,如 AFNetworking:
var sessionManager = AFHTTPSessionManager(baseURL: NSURL(string: "yavin4.yavin.planets")) sessionManager.HEAD("/api/destoryDeathStar", parameters: xwingSquad, success: { (NSURLSessionDataTask) -> Void in println("Success") }, failure:{ (NSURLSessionDataTask, NSError) -> Void in println("Failure") })
仍然是失败块经常收到NSError的实例,描述了错误。
程序员错误:
对于程序员错误(如数组元素的越界访问、传递给函数调用的无效参数等),您在 ObjC 中使用了异常。Swift 语言似乎没有任何语言支持异常(如throw, catch, 等关键字)。但是,正如文档所暗示的那样,它与 ObjC 在同一运行时运行,因此您仍然可以NSExceptions像这样抛出:
throw
catch
NSExceptions
NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()
尽管您可以选择在 ObjC 代码中捕获异常,但您无法在纯 Swift 中捕获它们。
问题是您是否应该为程序员错误抛出异常,或者更确切地说使用 Apple 在语言指南中建议的断言。