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)
})
我正在使用Xcode 12 RC生成错误:
发生错误:typeMismatch;应解码Double,但找到的却是字符串/数据&";,underlyingError:nil((。
我可以看到您在这里直接使用JSONDecoder()
,在您的模型中var publishedAt: Date?
是一个日期对象。
您需要首先配置解码器以解析字符串中的日期,然后使用它
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601 // <------- set date decoding strategy explicitly
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: decoder)
.eraseToAnyPublisher()
}
}