从 URLRequest dataTask 返回泛型类型
Posted
技术标签:
【中文标题】从 URLRequest dataTask 返回泛型类型【英文标题】:Returning generic type from a URLRequest dataTask 【发布时间】:2020-02-26 12:25:38 【问题描述】:我正在尝试构建一个通用函数,以便在 URLSession 的 dataTask 完成后返回给定类型的数组。
我有这个可解码:
struct Todo: Hashable, Codable, Identifiable
var id: Int
var title: String
var completed: Bool
还有这个功能:
func loadFrom<T: Decodable>(url: String, memberType: T, completionHandler: (T?) -> Void)
guard let url = URL(string: url) else
completionHandler(nil)
URLSession.shared.dataTask(with: url) data, response, error in
guard let data = data else
fatalError("No data returned")
do
let decoder = JSONDecoder()
let results = try decoder.decode(T.self, from: data)
completionHandler(results)
catch
fatalError("Couldn't parse data")
.resume()
loadFrom(url: "https://jsonplaceholder.typicode.com/todos?completed=true", memberType: Todo) response in
...
错误:Swift Scratchpad.playground:61:88:错误:参数类型“Todo.Type”不符合预期的类型“Decodable”
我看到了类似的问题,这些问题表明编译器无法综合 Decodable 协议要求的一致性方法,但是构建一个分配给 Decodable 类型而不是将其指定为参数的类似方法可以工作:
func loadFile<T: Decodable>(file: String) -> T
...
var todos: [Todo] = loadFile(file: "todos.json")
print(todos[0].title) => "The todo title"
我认为我的loadFrom
没有指定其返回类型是原因,但我不明白为什么。
是否有可能为这段代码提供足够的上下文来编译?
【问题讨论】:
【参考方案1】:在loadFrom(url:memberType:completionHandler:)
方法中,
1. 使用 T.Type
而不是 T
作为 memberType
的数据类型
2.将@escaping
添加到completionHandler
func loadFrom<T: Decodable>(url: String, memberType: T.Type, completionHandler: @escaping ((T?)->()))
像这样调用方法,
loadFrom(url: "https://jsonplaceholder.typicode.com/todos?completed=true", memberType: Todo.self) response in
...
另外,在guard
语句中添加return
,
guard let url = URL(string: url) else
completionHandler(nil)
return //here...
【讨论】:
【参考方案2】:你必须声明
func loadFrom<T: Decodable>(url: String, memberType: T.Type, completionHandler: @escaping (T?) -> Void)
然后调用它
loadFrom(url: "https://jsonplaceholder.typicode.com/todos?completed=true", memberType: Todo.self) response in
...
而不是不方便的致命错误添加一个更好的结果类型,以便能够在调用方法之前也返回错误并捕获错误的 URL
func loadFrom<T: Decodable>(url: URL, memberType: T.Type, completionHandler: @escaping (Result<T,Error>) -> Void)
URLSession.shared.dataTask(with: url) data, _, error in
if let error = error
completionHandler(.failure(error))
else
completionHandler( Result try JSONDecoder().decode(T.self, from: data!))
.resume()
【讨论】:
以上是关于从 URLRequest dataTask 返回泛型类型的主要内容,如果未能解决你的问题,请参考以下文章
NSURLSessionConfiguration 不返回 URLRequest 数据
Swift 4 将参数添加到 URLRequest 完成处理程序