从 URLRequest dataTask 返回通用类型
Returning generic type from a URLRequest dataTask
我试图在 URLSession 的 dataTask 完成后为 return 给定类型的数组构建一个通用函数。
我有这个 Decodable:
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
...
}
error: Swift Scratchpad.playground:61:88: error: argument type 'Todo.Type' does not conform to expected 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
没有指定其 return 类型是原因,但我不明白为什么。
是否可以为这段代码提供足够的上下文来编译?
您必须申报
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
...
}
而不是笨拙的 致命错误 添加更好的结果类型,以便能够 return 错误并捕获 错误 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()
}
在loadFrom(url:memberType:completionHandler:)
方法中,
1. 使用 T.Type
而不是 T
作为 memberType
[ 的数据类型=21=]
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...
}
我试图在 URLSession 的 dataTask 完成后为 return 给定类型的数组构建一个通用函数。
我有这个 Decodable:
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
...
}
error: Swift Scratchpad.playground:61:88: error: argument type 'Todo.Type' does not conform to expected 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
没有指定其 return 类型是原因,但我不明白为什么。
是否可以为这段代码提供足够的上下文来编译?
您必须申报
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
...
}
而不是笨拙的 致命错误 添加更好的结果类型,以便能够 return 错误并捕获 错误 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()
}
在loadFrom(url:memberType:completionHandler:)
方法中,
1. 使用 T.Type
而不是 T
作为 memberType
[ 的数据类型=21=]
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...
}