Swift:NSError现在应该被认为是遗产吗?

时间:2016-05-06 11:24:05

标签: ios swift error-handling

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

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

我已经将一个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实例吗?当然,我们可以运行代码以确保,但文档肯定应该让我们知道。 (我很欣赏我可能会误读文档)

2 个答案:

答案 0 :(得分:1)

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

我不确定Apple现阶段是否有任何关于如何处理这种二元性的声明,但我个人仍然坚持NSError为了我自己的错误而遵守Swift类型当我想根据一些Cocoa或第三方基于ErrorType的代码进行条件行为时,只涉及转换为ErrorType。代码组合在某种程度上对我的逻辑有意义(例如,如果可以从日志记录或响应中过滤掉特定错误)。

Swift中用于错误处理的现有工具的问题主要是因为无法判断方法引发了哪种错误,并且NSError缺少NSError中包含的一些关键上下文信息每当您想要以某种方式向用户呈现UI中的ErrorType时,它会提供额外的定制工作。与NSError不同,ErrorType没有办法传递UI预期信息,例如“原因”或“恢复建议”,或者实际上是“描述”。对于Swift 3来说,这似乎还没有得到解决(最近在Swift开发邮件列表上有一些关于此的讨论)。

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

我个人遵循制定NSError实现ErrorType并使用ErrorType属性来描述错误的人类(UI预期)可读描述的惯例。这绝不是完美的,特别是在OSX上,CustomStringConvertible很好地为您提供了description方法,如果您填写说明&恢复建议信息。

答案 1 :(得分:0)

NSError类采用ErrorType接口,任何符合ErrorType的符合类都可以转换为NSError。这些功能描述为here in the docs

您可以安全地坚持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!
}