自定义错误类型初始化程序

时间:2017-06-14 14:22:55

标签: swift

让我来说明为什么我认为这不是How to provide a localized description with an Error type in Swift?

的重复

提供的答案仍然会导致一些静态/类函数调用,而不是初始化器样式或需要转换为NSError(我想避免)。

简要总结原因:

throws未声明错误类型的Swift函数。我们无法强制catch传递一个简单符合Error协议的自定义类型。知道,在do-catch方面,我们没有得到编译器的帮助,因为我们得到了什么类型(如果是自定义的)错误,默认情况下我们期望已知的NSError属性。否则,我们需要简单地依赖文本文档来解释我们可以捕获的错误类型,因为catch只会传递Error类型。

现在,与NSError不同,Error是一种协议,我们在userInfo中获取的属性是只读的。因此我们求助于构造NSError类型,并将其转换为Error。

我正在尝试创建一个简单的clean结构,它返回一个Error类型(不是NSError),我可以像这样抛出:

throw MYError(domain: "com.somthing.error", code: 0, userInfo: [NSLocalizedDescriptionKey : "Something bad happened"])

主要问题是设置NSLocalizedDescriptionKey的唯一方法是初始化NSError对象。这样做需要转换为Error类型(这是我试图避免的)。

我首先尝试使用extension Error {...,但无法使用初始化程序。

如果我使用符合错误协议(struct MyError: Error {...)的结构,我仍然遇到localizedDescription仅获取的问题。

我使用的实际上是:

struct MYError: Error {

    static func with(domain: String = "com.somthing.error", code: Int = 0, localizedDescription: String) -> Error {
        return NSError(domain: domain, code: code, userInfo: [NSLocalizedDescriptionKey : localizedDescription]) as Error
    }
}

我可以使用它:

throw MYError.with(localizedDescription: "Some Error has happened")

直观地说,我希望像MYError这样的类型只使用初始值设定项MYError(domain:...,而不是静态函数。

Swifty方式更像是:

enum ErrorType: Error {
    case one
    case two
    case three(with: String)
}

...

// In some function:
throw ErrorThrown.three(with: "Three!")

...

// Catch like:
catch ErrorType.three(let str) {
    print("Error three: \(str)")
}

目前尚不清楚我们是否还在那里。似乎NSError仍在发挥作用,我知道我可以期望获得localizedDescription可选localizedFailureReason和熟悉的NSError属性。

3 个答案:

答案 0 :(得分:6)

How to provide a localized description with an Error type in Swift?类似 您可以定义采用LocalizedError的自定义错误类型 协议:

public struct MyError: Error {
    let msg: String

}

extension MyError: LocalizedError {
    public var errorDescription: String? {
            return NSLocalizedString(msg, comment: "")
    }
}

示例:

do {
    throw MyError(msg: "Something happened")
} catch let error {
    print(error.localizedDescription)
}

这将打印给定消息的本地化版本。 请注意,catch子句中的error是一般Error,所以 调用者不需要将其强制转换为具体的错误类型(甚至知道 抛出了哪种错误类型。)

答案 1 :(得分:4)

Error是一个协议,您可以抛出任何符合该协议的内容

例如

struct MYError : Error {
    let description : String
    let domain : String

    var localizedDescription: String {
        return NSLocalizedString(description, comment: "")
    }
}

你可以使用它:

func test() throws
{
  throw MYError(description: "Some Error has happened", domain: "com.somthing.error")
}
do {
    try test()
} catch let error as MYError{
    print("error: ", error.domain, error.localizedDescription)
}

答案 2 :(得分:2)

终于找到了一种在通用错误类型中粘贴任何东西的方法。 感谢 vadian Martin R ,我最终得到了答案。

归结为:

struct MyError: Error {

    var locString: String
    var reason: String?
    var code: Int
    var wish: String
}

// The errorDescription is the only part that actually comes generically with Error
extension MyError: LocalizedError {

    // This is actually part of LocalizedError
    var errorDescription: String? {
        return locString
    }
}

extension Error {

    var errorCode: Int {
        return (self as! MyError).code
    }

    var failureReason: String? {
        return (self as! MyError).reason
    }

    var everythingYouWishFor: String {
        return (self as! MyError).wish
    }
}

...

throw MyError(locString: "Localized string", reason: "The reason", code: 12, wish: "Best wishes")