ios - SwiftUI:API URL 获取失败
问题描述
我正在尝试从 API url 检索数据这是实施指南所读取的内容,因此 URL 应与以下格式匹配:
JSON 格式的信息请求作为 GET 操作提交到端点:
http://digit-eyes.com/gtin/v2_0/?upc_code=x&app_key=x&signature=x&language=x&field_names=x
这是我从 JSON 中获取数据并从 JSON 中解码的函数。我已经用 x 替换了签名和 API 密钥。签名是通过组合 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 时得到的 结果, 我已经使用以下命令测试了 URL:“https://itunes.apple.com/search?term=radiohead&entity=song”,它可以工作。一个明显的区别是这个链接下载一个 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)
}
}
}
}
这是在身体外部的结构中
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: "预期的字符串值,但找到了 null。",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?
}
推荐阅读
- python-3.x - 如何在开始消费者之前等待队列中的一些项目
- javascript - parseInt 在某些严格比较中失败( stringParsedToInteger === 3; // 返回未定义)
- java - 我在此代码中的 child() 错误中无法为参数 'pathString' 传递 null
- c# - 除非输入为 1,否则我的 C# 自动打字机类型比假定的输入多
- r - Inferring amortisation, remaining value and new loans from face value data
- jquery - 如何将当前页码和长度发送到服务器
- c++ - 如何在鼠标左键按下时触发循环 autoclicker c++
- mongodb - 如何在 mongodb 上计算/求和数组?
- typescript - 以类型安全的方式使可选参数的数量相同
- angular - Oauth1.0a Angular 2+