我正在尝试从 API url 检索数据
这是实现指南的内容,因此 URL 应与以下格式匹配:
The request for information in JSON format is submitted as a GET operation to the endpoint:
http://digit-eyes.com/gtin/v2_0/?upc_code=x&app_key=x&signature=x&language=x&field_names=x
这是我从 JSON 中获取数据并从 JSON 中解码的函数。
我已经用 x 替换了签名和 API key 。
签名是通过组合 app_key 和形成散列值的条形码生成的。
func loadData() {
guard let url = URL(string: "https://www.digit-eyes.com/gtin/v2_0/?upcCode=5901905880016&language=en&app_key=x&signature=x&language=en&field_names=description,brand,ingredients,image,upc_code") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, responce, error in
if let data = data {
if let decodedRepsonce = try? JSONDecoder().decode(Response.self, from: data) {
DispatchQueue.main.async{
self.results = decodedRepsonce.results
}
return
}
}
print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")") //This is the error I get
}.resume()
}
这是我将 URL 粘贴到 Safari 时得到的结果我已经用“https://itunes.apple.com/search?term=radiohead&entity=song”测试了这个 URL,它可以工作。一个明显的区别是这个链接下载一个 JSON 文件,我的 URL 没有。
我将 JSON 存储到数组结果中:
struct Result: Codable {
var description: String
var brand: String
var ingredients: String
var image: String
var upc_code: Int
}
然后显示在正文中:var body: some View {
GeometryReader { geometry in
VStack(spacing: 0) {
self.indicator.padding()
List(self.results, id: \.upc_code) { item in
VStack(alignment: .leading) {
Text(item.brand)
.font(.headline)
Text(item.description)
}
}
}
编辑 处理来自 JSON 数据的空值
要调用 loadData,我在正文的 VStack 上有一个 .onAppear。
.onAppear {
//let signiture = self.scannedCode.barcode.hashedValue("Ls75O8z1q9Ep9Kz0")
self.loadData(url: "https://www.digit-eyes.com/gtin/v2_0/?upcCode=5901905880016&language=en&app_key=/9nOS+obsRF5&signature=DiKl4lURenoNe53I0a/i3kiAkQQ=&language=en&field_names=description,ingredients,brand,image") { error, result in
if let err = error {
print(err)
}
}
}
}
这是在 body 外部的结构中 func loadData(url: String, completion: @escaping (Error?, Result?) -> Void) {
if let url = URL(string: url) {
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {return}
do {
let decoder = JSONDecoder()
let result: Result = try decoder.decode(Result.self, from: data)
completion(nil, result)
}
catch let e {
print(e)
completion(e, nil)
}
}
task.resume()
}
}
}
我现在得到:valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "brand", intValue: nil)], debugDescription: "Expected String value but found null instead.", underlyingError: nil))
在 JSON 对象中,品牌名称并不总是可以找到,因此它有时为空。如果找到空值,我不知道如何恢复解码器。
最佳答案
试试这段代码在正文中调用:
func loadData(url: String, completion: @escaping (Error?, Result?) -> Void) {
if let url = URL(string: url) {
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {return}
do {
let decoder = JSONDecoder()
let result: Result = try decoder.decode(Result.self, from: data)
completion(nil, result)
}
catch let e {
print(e)
completion(e, nil)
}
}
task.resume()
}
}
loadData(url: "https://google.com") { error, result in
if let err = error {
print(err)
}
}
尝试如下修改结构并添加其他变量。我还注意到 upc_code 是一个字符串。struct Result: Codable {
var description: String?
var brand: String?
var ingredients: String?
var image: String?
var upc_code: String?
var return_message: String?
var return_code: String?
}
关于ios - SwiftUI : API URL fetch failed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62739895/