import Foundation
import Combine
let liveSample = URL(string: "https://newsapi.org/v2/top-headlines?country=us&apiKey=<api key>")!
struct ArticleList: Codable {
struct Article: Codable {
struct Source: Codable {
var id: String?
var name: String?
}
var source: Source?
var author: String?
var title: String?
var description: String?
var url: URL?
var urlToImage: URL?
var publishedAt: Date?
var content: String?
}
var status: String
var totalResults: Int
var articles: [Article]
}
struct Resource<T: Codable> {
let request: URLRequest
}
extension URLSession {
func fetchJSON<T: Codable>(for resource: Resource<T>) -> AnyPublisher<T, Error> {
return dataTaskPublisher(for: resource.request)
.map { $0.data }
.decode(type: T.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}
}
var subscriber: AnyCancellable?
var resource: Resource<ArticleList> =
Resource<ArticleList>(request: URLRequest(url: liveSample))
subscriber?.cancel()
subscriber = URLSession.shared.fetchJSON(for: resource)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("The publisher finished normally.")
case .failure(let error):
print("An error occured: \(error).")
}
}, receiveValue: { result in
dump(result)
})
I am using Xcode 12 RC generates error:
An error occured: typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "articles", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "publishedAt", intValue: nil)], debugDescription: "Expected to decode Double but found a string/data instead.", underlyingError: nil)).
publishedAt
in the array for keyarticles
is a string. To decode the value toDate
you have to add the.iso8601
date decoding stretegy. The default date decoding strategy expects aTimeInterval
(aka aDouble
). – vadian