如何在Swift 3中覆盖自定义错误的localizedDescription?

40

错误协议只有一个属性 localizedDescription。

我尝试创建从NSObject和Error继承的自定义对象,但无法覆盖localizedDescription。该怎么做?

这段代码不允许我获取自定义描述:

class MyError: NSObject, Error {
    var desc = ""
    init(str: String) {
        desc = str
    }
    override var description: String {
        get {
            return "MyError: \(desc)"
        }
    }
   var localizedDescription: String {
        get {
            return self.description
        }
    }
}

func test_my_code() {
    let error = MyError(str: "my test string")
    let x = error as Error
    print(x.localizedDescription)
}

调用函数"test_my_code"时得到了意外结果:"操作无法完成..."。

为了获得"MyError: my test string"结果,我该怎么做?


你不需要使用 override 吗? - Sunil Chauhan
你不能通过添加一个新属性来扩展Error类,然后读取它吗? - mfaani
1
@SunilChauhan 不可以。协议中的任何内容都不应该被覆盖。添加“override”将导致编译错误。 - Maxim Kholyavkin
@Honey,我不想扩展协议。我只是想创建一个符合Error协议的自定义类。 - Maxim Kholyavkin
@Speakus 哎呀,我错过了那个! - Sunil Chauhan
2个回答

78

关于新的错误桥接功能的文档仍然不够清晰,因此本答案可能需要在不久的将来进行更新,但根据SE-0112最新的Swift源代码,您可能需要使用LocalizedError而不是Error并实现errorDescription

class MyError: NSObject, LocalizedError {
    var desc = ""
    init(str: String) {
        desc = str
    }
    override var description: String {
        get {
            return "MyError: \(desc)"
        }
    }
    //You need to implement `errorDescription`, not `localizedDescription`.
    var errorDescription: String? {
        get {
            return self.description
        }
    }
}

func test_my_code() {
    let error = MyError(str: "my test string")
    let x = error as Error
    print(x.localizedDescription)
}
test_my_code() //->MyError: my test string

除了使用LocalizedError,这个默认实现也可以工作:
(在上面显示的链接中的NSError.swift)
public extension Error {
    /// Retrieve the localized description for this error.
    var localizedDescription: String {
        return NSError(domain: _domain, code: _code, userInfo: nil).localizedDescription
    }
}

这里涉及到Swift如何从任意符合Error协议的类型定义_domain_code,有点复杂。但似乎NSError会对未知的域和代码组合生成“无法完成操作”的错误信息。请注意保留HTML标签。

太好了!我之前一直在苦恼这个问题,还用了丑陋的switch/case语句。现在完美解决了! - denis631

18
如果自定义类型符合协议CustomStringConvertible并提供了本地化的description,那么下面的LocalizedError扩展可能会有用:
extension LocalizedError where Self: CustomStringConvertible {

   var errorDescription: String? {
      return description
   }
}

示例代码:

class MyError: LocalizedError, CustomStringConvertible {

   let desc: String

   init(str: String) {
      desc = str
   }

   var description: String {
      let format = NSLocalizedString("Operation error: %@", comment: "Error description")
      return String.localizedStringWithFormat(format, desc)
   }
}


let error = MyError(str: "my test string")
let x = error as Error
print(x.localizedDescription) // Prints "Operation error: my test string"
print(String(describing: x))  // Prints "Operation error: my test string"

这是这里最好的答案。认真地遵循CustomStringConvertible并提供var description: String - TaborKelly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接