Reputation: 99
I am trying to define a protocol for which I would like to add conformance to several Foundation classes as well as some custom types of my own. I first tried doing this with a convenience initializer in the protocol, but that does not seem possible. I read in the linked thread on the Apple dev forums where they talked about using a class method that returns type Self, but I am unable to figure out how to go about this.
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'
}
}
I found a similar question but the answer there was to mark the class as final -- I obviously can't do that on a Foundation class.
Could someone explain how to fix my approach above? Or suggest a different approach for adding protocol conformance to Foundation classes?
Upvotes: 2
Views: 384
Reputation: 8401
Use self.init(....)
instead of NSURL(....)
since this also needs to work for NSURL
subclasses.
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 : define a typealias T
, this will return an NSURL
even for subclasses.
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
}
}
Upvotes: 2