我正在学习在Xcode游乐场中使用JSON解码数据,但无法弄清楚我的代码有什么问题,我无法返回数据或解码数据。 这是我的代码:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
extension URL {
func withQueries(_ queries: [String: String]) -> URL? {
var components = URLComponents(url: self, resolvingAgainstBaseURL: true)
components?.queryItems = queries.flatMap { URLQueryItem(name: $0.0, value: $0.1) }
return components?.url
}
}
struct StoreItems: Codable {
let results: [StoreItem]
}
struct StoreItem: Codable {
var name: String
var artist: String
var kind: String
var artworkURL: URL
var description: String
enum CodingKeys: String, CodingKey {
case name = "trackName"
case artist = "artistName"
case kind
case artworkURL
case description
}
enum AdditionalKeys: String, CodingKey {
case longDescription
}
init(from decoder: Decoder) throws {
let valueContainer = try decoder.container(keyedBy: CodingKeys.self)
name = try valueContainer.decode(String.self, forKey: CodingKeys.name)
artist = try valueContainer.decode(String.self, forKey: CodingKeys.artist)
kind = try valueContainer.decode(String.self, forKey: CodingKeys.kind)
artworkURL = try valueContainer.decode(URL.self, forKey: CodingKeys.artworkURL)
if let description = try? valueContainer.decode(String.self, forKey: CodingKeys.description) {
self.description = description
} else {
let additionalValues = try decoder.container(keyedBy: AdditionalKeys.self)
description = (try? additionalValues.decode(String.self, forKey: AdditionalKeys.longDescription)) ?? ""
}
}
}
func fetchItems(matching query: [String: String], completion: @escaping ([StoreItem]?) -> Void) {
let baseURL = URL(string: "https://www.itunes.apple.com/search?")!
guard let url = baseURL.withQueries(query) else {
completion(nil)
print("Unable to build URL with supplied queries.")
return
}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
let decoder = JSONDecoder()
if let data = data,
let storeItems = try? decoder.decode(StoreItems.self, from: data) {
completion(storeItems.results)
} else {
print("Either no data was returned or data was not properly decoded.")
completion(nil)
return
}
}
task.resume()
}
let query: [String: String] = [
"term": "Inside Out 2015",
"media": "movie",
"lang": "en_us",
"limit": "10"
]
fetchItems(matching: query) { (items) in
print(items)
}
以下是打印到控制台的内容,我猜这表明我的任务有什么问题":
未返回任何数据或数据未正确解码。
零
答案 0 :(得分:1)
有几个问题:
www
。artworkURL
似乎是可选的,因为您的搜索没有返回该密钥的值。当我修复它们时,它起作用:
extension URL {
func withQueries(_ queries: [String: String]) -> URL? {
var components = URLComponents(url: self, resolvingAgainstBaseURL: true)
components?.queryItems = queries.flatMap { URLQueryItem(name: $0.0, value: $0.1) }
return components?.url
}
}
struct StoreItems: Codable {
let results: [StoreItem]
}
struct StoreItem: Codable {
var name: String
var artist: String
var kind: String
var artworkURL: URL?
var shortDescription: String?
var longDescription: String?
enum CodingKeys: String, CodingKey {
case name = "trackName"
case artist = "artistName"
case kind, artworkURL, shortDescription, longDescription
}
}
enum FetchError: Error {
case urlError
case unknownNetworkError
}
func fetchItems(matching query: [String: String], completion: @escaping ([StoreItem]?, Error?) -> Void) {
let baseURL = URL(string: "https://itunes.apple.com/search")!
guard let url = baseURL.withQueries(query) else {
completion(nil, FetchError.urlError)
return
}
let task = URLSession.shared.dataTask(with: url) { data, _, error in
guard let data = data, error == nil else {
completion(nil, error ?? FetchError.unknownNetworkError)
return
}
do {
let storeItems = try JSONDecoder().decode(StoreItems.self, from: data)
completion(storeItems.results, nil)
} catch let parseError {
completion(nil, parseError)
}
}
task.resume()
}
和
let query = [
"term": "Inside Out 2015",
"media": "movie",
"lang": "en_us",
"limit": "10"
]
fetchItems(matching: query) { items, error in
guard let items = items, error == nil else {
print(error ?? "Unknown error")
return
}
print(items)
}
注意,我建议您将错误添加到完成处理程序,以便您可以看到为什么它失败(在您的情况下,第一个问题是URL错误)。
答案 1 :(得分:0)
这不是具体的解决方案,而是建议如何调试解码。
使用以下代码替换以if let data = data,
开头的整个表达式并调试代码。 <{1}}返回的潜在(在您的情况下确定)错误也被处理。
dataTask