如何解决Swift 语言中的错误处理
斯威夫特 2 & 3
Swift 2 中的情况发生了一些变化,因为有一个新的错误处理机制,它有点类似于异常,但在细节上有所不同。
1.指示错误可能性
如果函数/方法想要表明它可能会抛出错误,它应该包含throws
这样的关键字
func summonDefaultDragon() throws -> Dragon
注意:函数实际上可以抛出的错误类型没有规范。 这个声明只是声明函数可以抛出任何实现 ErrorType 类型的实例,或者根本不抛出。
2.调用可能抛出错误的函数
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?
:
let dragonorNil = try? summonDefaultDragon()
这样,如果发生任何错误,您要么得到返回值,要么得到 nil。使用这种方式你不会得到错误对象。
这意味着您还可以结合try?
有用的语句,例如:
if let dragon = try? summonDefaultDragon()
或者
guard let dragon = try? summonDefaultDragon() else { ... }
最后,您可以确定您知道错误实际上不会发生(例如,因为您已经检查了先决条件)并使用try!
关键字:
let dragon = try! summonDefaultDragon()
如果函数确实抛出错误,那么您将在应用程序中收到运行时错误,并且应用程序将终止。
3. 抛出错误
为了抛出错误,您可以使用 throw 关键字这样
throw DragonError.dragonIsMissing
你可以抛出任何符合ErrorType
协议的东西。对于初学者NSError
,符合此协议,但您可能希望使用基于枚举的方法ErrorType
,它使您能够对多个相关错误进行分组,可能还有额外的数据,像这样
enum DragonError: ErrorType {
case dragonIsMissing
case notEnoughMana(requiredMana: Int)
...
}
新的 Swift 2 和 3 错误机制与 Java/C#/C++ 样式异常的主要区别如下:
- 语法有点不同:++
do-catch
vs传统语法。try``defer``try-catch-finally
- 异常处理在异常路径中的执行时间通常比在成功路径中要长得多。Swift 2.0 错误并非如此,成功路径和错误路径的成本大致相同。
- 必须声明所有抛出错误的代码,而可能从任何地方抛出异常。在 Java 命名法中,所有错误都是“检查异常”。但是,与 Java 相比,您不指定可能引发的错误。
- Swift 异常与 ObjC 异常不兼容。您的
do-catch
块不会捕获任何 NSException,反之亦然,因为您必须使用 ObjC。 - Swift 异常与返回(用于返回函数)或(用于返回函数)并传递错误详细信息的 Cocoa
NSError
方法约定兼容。false``Bool``nil``AnyObject``NSErrorPointer
作为简化错误处理的额外语法糖,还有两个概念
- 延迟操作(使用
defer
关键字),它可以让您实现与 Java/C#/etc 中的 finally 块相同的效果 - 保护语句(使用
guard
关键字),它让你编写的 if/else 代码比正常的错误检查/信号代码少一些。
斯威夫特 1
正如 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
像这样抛出:
NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()
尽管您可以选择在 ObjC 代码中捕获异常,但您无法在纯 Swift 中捕获它们。
问题是您是否应该为程序员错误抛出异常,或者更确切地说使用 Apple 在语言指南中建议的断言。
解决方法
我对 Swift 的了解并不多,但我注意到的一件事是没有例外。那么他们如何在 Swift 中进行错误处理呢?有没有人发现任何与错误处理有关的东西?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。