I'm making a history of today iOS app using the API http://history.muffinlabs.com/date/4/19
Here is the data struct of me:
struct HistoryAPIResponse: Codable {
let data: [Events]
}
struct Events: Codable {
let year: String
let text: String
let html: String
}
And here's how I fetch the data from it:
import Foundation
import UIKit
final class HistoryAPICaller {
static let shared = HistoryAPICaller()
struct Constants {
static let topHeadLinesURL = URL(string:
"http://history.muffinlabs.com/date/4/19"
)
static let searchUrlString =
"http://history.muffinlabs.com/date/4/19"
}
private init() {}
public func getTopStories(completion: @escaping (Result<[Events], Error>) -> Void) {
guard let html = Constants.topHeadLinesURL else {
return
}
let task = URLSession.shared.dataTask(with: html) { data, _, error in
if let error = error {
completion(.failure(error))
}
else if let data = data {
do {
_ = try JSONDecoder().decode(HistoryAPIResponse.self, from: data)
}
catch {
completion(.failure(error))
}
}
}
task.resume()
}
public func search(with query: String, completion: @escaping (Result<[Events], Error>) -> Void) {
guard !query.trimmingCharacters(in: .whitespaces).isEmpty else {
return
}
let urltring = Constants.searchUrlString + query
guard let html = URL(string:urltring) else {
return
}
let task = URLSession.shared.dataTask(with: html) { data, _, error in
if let error = error {
completion ( .failure(error))
}
else if let data = data {
do {
_ = try JSONDecoder().decode(HistoryAPIResponse.self, from: data)
}
catch {
completion (.failure(error))
}
}
}
task.resume()
}
}
And in come one of the error message says:
typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil)], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
I kind of understand the nature of the problem, that data is a dictionary, but I don't know how to solve it considering this is the structure of the API, that everything stores in the [data]
.
Any idea how to solve this issue? Appreciate the help in advance.
You need
let res = try JSONDecoder().decode(Root.self, from: data)
struct Root: Codable {
let data: HistoryAPIResponse
}
struct HistoryAPIResponse: Codable {
let events: [Events]
private enum CodingKeys : String, CodingKey {
case events = "Events"
}
}
struct Events: Codable {
let year,text,html: String
}