我有下面两个函数,用来帮助解析Swift中的JSON。第一个函数可以很好地处理我抛出的任何JSON
第二种方法是让我感到不适,但我无法解决问题。我基本上想做与第一个函数相同的事情,但我的数据来自URLSession,而不是本地文件。
你知道我在这里做错了什么吗?我得到一个奇怪的编译器错误,void函数中意外的非void返回值,但签名完全相同。
import Foundation
import SwiftUI
// Populates Model from local files
public func loadFromJson<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let path = Bundle.main.path(forResource: filename, ofType: "json")
else{
fatalError("(filename) not found.")
}
do {
let file = URL(fileURLWithPath: path)
data = try Data(contentsOf: file)
} catch {
fatalError("Could not load (filename): (error)")
}
do{
return try JSONDecoder().decode(T.self, from: data)
} catch {
fatalError("Unable to parse (filename): (error)")
}
}
// Populates Model from REST endpoint
public func loadFromJsonFromURL<T: Decodable>(_ urlString: String) -> T {
let data: Data
let url = URL(string: urlString)!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
fatalError("Error: (error.localizedDescription)")
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
fatalError("Error: invalid HTTP response code")
}
guard let data = data else {
fatalError("Error: missing response data")
}
do {
return try JSONDecoder().decode(T.self, from: data)
}
catch {
print("Error: (error.localizedDescription)")
}
}
task.resume()
}
dataTask(with: completionHandler:)
是异步方法。因此,直到收到响应后调用completionHandler
时,方法loadFromJsonFromURL(_:_:)
已经返回。
在收到API的响应后,需要使用closure
将数据传递回。
public func loadFromJsonFromURL<T: Decodable>(_ urlString: String, _ handler: @escaping ((T?)->())) {
if let url = URL(string: urlString) {
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
fatalError("Error: (error.localizedDescription)")
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
fatalError("Error: invalid HTTP response code")
}
guard let data = data else {
fatalError("Error: missing response data")
}
do {
let value = try JSONDecoder().decode(T.self, from: data)
handler(value)
}
catch {
print("Error: (error.localizedDescription)")
handler(nil)
}
}
task.resume()
}
}