I'm currently trying to utilize the NewsApi api to allow me to retrieve certain articles. I currently do have a model for which I generated
import Foundation
// MARK: - Welcome
struct NewsResponse: Codable {
let status: String
let totalResults: Int
let articles: [Article]
enum CodingKeys: String, CodingKey {
case status = "status"
case totalResults = "totalResults"
case articles = "articles"
}
}
// MARK: - Article
struct Article: Codable, Identifiable {
let id = UUID()
let source: Source
let author: String?
let title: String
let articleDescription: String
let url: String
let urlToImage: String?
let publishedAt: Date
let content: String
enum CodingKeys: String, CodingKey {
case source = "source"
case author = "author"
case title = "title"
case articleDescription = "description"
case url = "url"
case urlToImage = "urlToImage"
case publishedAt = "publishedAt"
case content = "content"
}
}
// MARK: - Source
struct Source: Codable {
let id: String?
let name: String
enum CodingKeys: String, CodingKey {
case id = "id"
case name = "name"
}
}
I also do have my Webservice that decodes the API link which is at let pokeNews = URL(string:"https://newsapi.org/v2/everything?q=pokemon&apiKey=*APIKey*")!
The webservice code is here and I had used a Mohammed Azam tutorial for that: https://www.youtube.com/watch?v=YOCZuZz4vAw
import Foundation
class NewsWebService: ObservableObject{
@Published var news: [Article] = []
func getNews() async throws{
let (data, _) = try await URLSession.shared.data(from: Constants.url.pokeNews)
Task{@MainActor in
self.news = try JSONDecoder().decode([Article].self, from: data)
}
}
}
Now the main issue I'm having is that I'm at a loss of understanding at how I would access the articles array from the NewsResponse model and retrieve the article.title, etc. I've attempted it multiple times, but am not quite sure how to proceed. I've looked at other tutorials, but I feel that I'm still not gaining a sense of understanding at how to effectively call apis in swift. The code in which I'm attempting to call the API within is here:
import SwiftUI
struct NewsListView: View {
@EnvironmentObject var newsWebService: NewsWebService
var body: some View {
List(newsWebService.news){ article in
Text(article.title)
}
HStack(alignment: .center, spacing: 16, content: {
//Article Image
Image("yak0")
.resizable()
.scaledToFill()
.frame(width: 50, height: 50)
.clipShape(RoundedRectangle(cornerRadius: 12))
//Article Title
VStack(alignment: .leading, spacing: 8){
Text("Massive News Surrounding Pokemon")
.font(.title2)
.fontWeight(.heavy)
.foregroundColor(.red)
//Article Source
Text("CNN").font(.footnote)
.fontWeight(.bold)
.multilineTextAlignment(.leading)
.foregroundColor(.yellow)
}
}).onTapGesture {
//go to webview
}
}
}
struct NewsListView_Previews: PreviewProvider {
static var previews: some View {
NewsListView()
.previewLayout(.sizeThatFits)
.padding()
.environmentObject(NewsWebService())
}
}
Any help would be appreciated. Thank you so much!
Edited for NewsResponse portion
import Foundation
class NewsWebService: ObservableObject{
@Published var news: NewsResponse?
func getNews() async throws{
let (data, _) = try await URLSession.shared.data(from: Constants.url.pokeNews)
Task{@MainActor in
self.news = try JSONDecoder().decode(NewsResponse.self, from: data)
}
}
}
The Line showing the error: Initializer 'init(_:rowContent:)' requires that 'NewsResponse' conform to 'RandomAccessCollection'
List(newsWebService.news!){ article in
Text(article.title)
}