当使用一个泛型来调用另一个泛型时,我有一个有趣的编译错误。这篇文章有点长,但希望它不会超过描述问题所需的时间。
我已经定义了一个效果很好的通用函数。我经常使用它,使用模式通常是一样的。我试图实现一个嵌套现有泛型函数的新泛型函数,但我得到了一个编译时错误。
对于某些上下文,以下是我的API如何与通用工具一起使用。我的REST API调用films()func,它击中StarWarsAPI(swapi.co)并返回他们在数据库中拥有的所有星球大战电影的列表,如下所示:
StarWarsAPI.shared.films(){ (films, error) in
for film in films {
print(film.title)
}
}
films()函数调用泛型(restCall()),效果很好。这是电影()的定义:
public func films(completion: @escaping (_ films:[Film]?, _ error:StarWarsError?) -> Void) {
guard StarWarsAPI.isOperational else {
return completion(nil,StarWarsError.starWarsAPINotOperational)
}
restCall(fetchUrl: filmsUrl!, modelType: FilmResult()) { (filmResults, error ) in
completion(filmResults?.results, error)
}
}
其中restCall(通用)定义如下:(注意我使用Swift 4 Codable API)
public func restCall<T: Codable>(fetchUrl: URL, modelType: T, completion: @escaping (_ modelObject: T?, _ error:StarWarsError?) -> Void){
var fetchRequest = URLRequest(url: fetchUrl, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
fetchRequest.httpMethod = "GET"
fetchRequest.allHTTPHeaderFields = [
"content-type": "application/json",
"cache-control": "no-cache",
]
let session = URLSession.shared
let fetchDataTask = session.dataTask(with: fetchRequest) { (data, response, error) in
DispatchQueue.main.async { // return to main thread
var modelObject:T?
do {
let jsonDecoder = JSONDecoder()
modelObject = try jsonDecoder.decode(T.self, from: data)// FIXME: Something about decoding the People object is going wrong.
return completion(modelObject, nil)
}catch let error as NSError {
completion(nil, StarWarsError.decodingModelError(error: error))
}
}
}
fetchDataTask.resume()
}
所以上面的作品很棒。我将它用于休息函数film(),people(),ships()等。我为每次休息调用使用相同的模式。我想创建一个我可以使用的泛型而不是显式的film(),people()等。
我一直试图让以下工作取得成功:
public func fetchAll<T: Result>(result:T, completionAll: @escaping (_ result:T?, _ error:StarWarsError?) -> Void) {
restCall(fetchUrl: result.urlPath!, modelType: T) { (finalResults, error ) in
completionAll(finalResults!, error)
}
}
其中结果类型是基本类型,定义如下:
public class Result {
var urlPath:URL?
}
public class FilmResult: Result, Codable {
var count:Int?
var next:String?
var previous:String?
var results:[Film]?
}
我收到的错误显示在下面的屏幕截图中 - 希望很清楚。
非常感谢您提供的任何帮助!
答案 0 :(得分:1)
您的电话必须是
this was T previously ───┐
restCall(fetchUrl: result.urlPath!, modelType: result) { (finalResults, error ) in
请注意result
而不是T
。
重现的代码相对最少:
public func restCall<T>(fetchUrl: URL, modelType: T, completion: @escaping (_ modelObject: T?, _ error:String?) -> Void) { }
public func fetchAll<T>(result:T, completionAll: @escaping (_ result:T?, _ error:String?) -> Void) {
┌── should be result
restCall(fetchUrl: URL(string: "asdasd")!, modelType: T) { (finalResults, error ) in
completionAll(finalResults, error)
}
}