Swift:从 URL 加载 JSON 数据
Posted
技术标签:
【中文标题】Swift:从 URL 加载 JSON 数据【英文标题】:Swift: Loading JSON data from a URL 【发布时间】:2021-06-21 05:33:45 【问题描述】:我正在尝试修改地标教程中的 Apple 代码,以从远程 URL 加载 JSON 数据。 url 是一个 php 脚本,它返回纯文本 JSON 数据。
苹果的代码:
func loadLocalJSON<T: Decodable>(_ filename: String) -> T
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else
fatalError("Couldn't find \(filename) in main bundle")
do
data = try Data(contentsOf: file)
catch
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
do
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
catch
fatalError("Couldn't parse \(filename) from main bundle:\n\(error)")
以及我当前修改的代码:
func loadRemoteJSON<T: Decodable>(_ urlString: String) -> T
let data: Data
guard let url = URL(string: urlString) else
fatalError("Invalid URL")
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) data, response, error in
guard let data = data else
fatalError(error?.localizedDescription ?? "Unknown Error")
do
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data) // <--ERROR HERE
catch
fatalError("Couldn't parse data from \(urlString)\n\(error)")
我得到的错误是Unexpected non-void return value in void function
我认为该函数应该返回一个 T 的实例。我哪里出错了?
【问题讨论】:
"我得到的错误是 Unexpected non-void return value in void function" Where!? 您的 URL 会话缺少某些内容。 这能回答你的问题吗? Unexpected Non-Void Return Value In Void Function (Swift 2.0) 我认为您需要一个完成块而不是返回。如果您使用新的 async-await,则 return 很好,但此代码不适用于此。 我同意@RajaKishan-如果你正在运行异步任务,你不应该使用 return,你的变量的值可能会被loadRemoteJSON
初始化为 nil,因为 Swift 将继续前进通过您的代码,而无需等待该变量的初始化。
【参考方案1】:
您需要一个完成块而不是返回类型。您正在执行异步任务。 URLSession.shared.dataTask
是异步类型。
func loadRemoteJSON<T: Decodable>(_ urlString: String, completion: @escaping ((T) -> Void))
let data: Data
guard let url = URL(string: urlString) else
fatalError("Invalid URL")
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) data, response, error in
guard let data = data else
fatalError(error?.localizedDescription ?? "Unknown Error")
do
let decoder = JSONDecoder()
let data = try decoder.decode(T.self, from: data)
completion(data)
catch
fatalError("Couldn't parse data from \(urlString)\n\(error)")
用法:
struct TestModel: Decodable
var name: String
loadRemoteJSON("urlstring") (data: TestModel) in
print(data.name)
如果您使用的是 Swift 5.5,那么您可以使用 Async Await 返回您的数据。网上有很多文章和视频。您可以查看this。
【讨论】:
【参考方案2】:func loadRemoteJSON<T: Decodable>(_ urlString: String,completion: @escaping (T)->Void)
使用完成块很简单,只需解码 JSON 并将其传递给您的完成处理程序。
let decodedJSON = try decoder.decode(T.self, from: data)
completion(decodedJSON)
现在,当您调用 loadRemoteJSON
时,您将能够访问函数完成块内的 JSON,例如:
loadRemoteJSON(urlString: someString) data in
//data is your returned value of the generic type T.
【讨论】:
以上是关于Swift:从 URL 加载 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中将 JSON 加载到 UItableView
如何在 Swift 中从同一站点重新加载新的 JSON 数据?