Swift:NSError现在应该被视为遗留问题吗



文档和流行的博客建议使用do catch来处理Swift错误,并处理ErrorType枚举或NSError实例。

ErrorType枚举和NSError实例在try-catch块中是否互斥?如果没有,如何实现同时抛出这两个函数的函数?

我已经将NSError实例与类似的枚举相关联,这似乎有效,但这是返回详细错误信息的实际方式吗?

enum Length : ErrorType {
    case NotLongEnough(NSError)
    case TooLong(NSError)
}
func myFunction() throws {
    throw Length.NotLongEnough(NSError(domain: "domain", code: 0, userInfo: [NSLocalizedFailureReasonErrorKey: "Not long enough mate"]))
}
do {
    try myFunction()
} catch Length.NotLongEnough(let error) {
    print("(error)")
}

此示例显示如何将ErrorType强制转换为NSError。

do {
    let str = try NSString(contentsOfFile: "Foo.bar",
                           encoding: NSUTF8StringEncoding)
}
catch let error as NSError {
    print(error.localizedDescription)
}

我找不到符合NSString的ErrorType的错误枚举,所以我们应该假设它是NSError实例吗?当然,我们可以运行代码,但肯定的是,文档应该让我们知道。(我很感激我可能读错了文档)

任何ErrorType都可以成功地转换为NSError,这意味着如果您想将ErrorType作为优先级处理,或者特定的符合ErrorType的Swift类型,您应该在转换为NSError的情况之前处理这些情况(同样,这将成功用于所有符合ErrorType的蚂蚁类型)。

我不确定苹果在现阶段是否对如何处理这种二元性表达了任何规范性的意见,但就我个人而言,我试图坚持使用符合ErrorType的Swift类型来解决我自己的错误,并且只有当我想基于一些基于Cocoa或第三方NSError的代码进行条件行为时,才涉及转换为NSError;代码组合在某种程度上对我的逻辑有意义(例如,如果可以从日志记录或响应中过滤出特定的错误)。

Swift中现有的错误处理功能的问题主要是由于无法判断一个方法抛出了什么样的错误,再加上ErrorType缺乏NSError中包含的一些关键上下文信息,每当你想以某种方式在UI中向用户呈现ErrorType时,就会提供额外的定制工作。与NSError不同,ErrorType没有传递UI预期信息的方法,例如"原因"、"恢复建议"或"描述"。Swift 3似乎也不会解决这个问题(最近在Swift开发邮件列表上对此进行了一些讨论)。

关于"我找不到符合NSString的ErrorType的错误枚举",我真的不确定我是否正确理解了这个短语,也不确定它的总体措辞是否正确,但可能以下内容是相关的:

我个人遵循的惯例是,将我的ErrorType实现设为CustomStringConvertible,并使用description属性来描述错误的人工(UI)可读描述。这绝非完美,尤其是在OSX上,NSResponder很好地为您提供了presentError方法,如果您填写描述&恢复建议信息。

NSError类采用ErrorType接口,任何符合ErrorType的类都可以广播到NSError。这些功能在文档中有描述。

您可以安全地使用ErrorType,特别是如果您计划只与Swift进行互操作。

enum CommonError: ErrorType {
    case InternalInconsistency(String)
}
func boom() throws {
    throw CommonError.InternalInconsistency("Boom!")
}
do {
    try boom()
} catch {
    print(error) // InternalInconsistency("Boom!")
    print(error as NSError) // Error Domain=CommonError Code=0 "(null)"
}
do {
    try boom()
} catch let CommonError.InternalInconsistency(msg) {
    print("Error: (msg)") // Error: Boom!
}

最新更新