扩展 Foundation 类 以符合 Swift 协议

extending Foundation classes to conform to Swift protocol

我正在尝试定义一个协议,我想为其添加与多个 Foundation classes 以及我自己的一些自定义类型的一致性。我首先尝试使用协议中的便利初始值设定项来执行此操作,但是在 Apple 开发论坛上 does not seem possible. I read in the linked thread 他们讨论了使用 returns 类型 Self 的 class 方法,但我无法弄清楚如何去做。

typealias JSONObject = AnyObject
protocol JSONParseable {
    static func fromJSONObject(jsonObject: JSONObject) throws -> Self
}

extension NSURL: JSONParseable {
    class func fromJSONObject(jsonObject: JSONObject) throws -> Self {
        guard let jsonString = jsonObject as? String else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        guard let result = NSURL(string: jsonString) else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        return result // Error: cannot convert return expression of type 'NSURL' to return type 'Self'
    }
}

我找到了一个 similar question,但那里的答案是将 class 标记为最终答案——我显然不能在 Foundation class.[=15= 上这样做]

有人可以解释一下如何解决我上面的方法吗?或者建议一种不同的方法来向 Foundation 添加协议一致性 classes?

使用 self.init(....) 而不是 NSURL(....) 因为这也需要对 NSURL 子类起作用。

protocol JSONParseable {
    static func fromJSONObject(jsonObject: JSONObject) throws -> Self
}

extension NSURL : JSONParseable {

    class func fromJSONObject(jsonObject: JSONObject) throws -> Self {

        guard let jsonString = jsonObject as? String else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        guard let result = self.init(string: jsonString) else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        return result
    }
}

Hack:定义一个 typealias T,这将 return 一个 NSURL 甚至对于子类也是如此。

protocol JSONParseable {
    typealias T = Self
    static func fromJSONObject(jsonObject: JSONObject) throws -> T
}

extension NSURL : JSONParseable {

    typealias T = NSURL
    class func fromJSONObject(jsonObject: JSONObject) throws -> T {

        guard let jsonString = jsonObject as? String else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        guard let result = NSURL(string: jsonString) else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        return result
    }
}