Reputation: 8991
I have a protocol that defines the ability to fetch an array of objects from a server. Result
is defined in Alamofire:
protocol BulkFetchable {
static func fetch(limit : Int, skip : Int, completionHandler : ((request : NSURLRequest?, response : NSHTTPURLResponse?, result : Result<[Self]?>) -> Void)) -> Request
}
I extend this protocol with a generic implementation (ignore the fact that that the endpoint is fixed for the purposes of this question):
extension BulkFetchable where Self : Mappable {
static func fetch(limit: Int, skip: Int, completionHandler: ((request: NSURLRequest?, response: NSHTTPURLResponse?, result: Result<[Self]?>) -> Void)) -> Request {
return Alamofire.request(.GET, "http://localhost:4567/users.json", parameters: ["limit" : limit, "skip" : skip], encoding: .URL, headers: nil).responseArray(completionHandler)
}
}
I'm using an extension to Alamofire Request
that converts a JSON response to an optional array of type T
, where T
adopts Mappable
:
extension Request {
func responseArray <T : Mappable> (completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<[T]?>) -> Void) -> Self {
return responseJSON(completionHandler: { (req, res, result) -> Void in
switch result {
case .Success(let json):
completionHandler(req, res, .Success(Mapper<T>().mapArray(json)))
break
case .Failure(let data, let error):
completionHandler(req, res, .Failure(data,error))
break
}
})
}
}
Then, I give my User
model this ability:
extension User : BulkFetchable {}
Alas, I receive the error:
Protocol 'BulkFetchable' requirement 'fetch(_:skip:completionHandler:)' cannot be satisfied by a non-final class ('User') because it uses 'Self' in a non-parameter, non-result type position
What can I do to get around this? I would expect that Self
automatically becomes User
in the context of the extension to User
, but that's probably due to my lack of understanding.
Upvotes: 1
Views: 1210
Reputation: 61
I was doing something similar and stumbled on the same error.
My limited understanding of this (which comes mostly from two videos recorded at WWDC 2015 here and here) suggests that your class User needs to be declared as:
final class User {...}
This would be because the fetch()
call doesn't have to be overridden by a subclass.
fetch()
is supposed to return a homogenous array of Self (in this case User
) and if User
was subclassed (and fetch()
overriden) it would return an array of the subclass. Or in an easily imagined world an array of User
and its subclasses. Not what the super class BulkFetchable
was expecting!
Upvotes: 6