我目前正试图利用NewsApi来检索某些文章.我目前确实有一个我生成的模型

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"
    }
}

我也有我的Webservice,它可以解码let pokeNews = URL(string:"https://newsapi.org/v2/everything?q=pokemon&apiKey=*APIKey*")!的API链接

webservice代码在这里,我使用了MohammedAzam教程: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)
        }
        
    }
    
}

现在我面临的主要问题是,我无法理解如何从NewsResponse模型访问articles数组并检索文章.标题等.我已经try 过多次,但不太确定如何继续.我看过其他教程,但我觉得我仍然没有理解如何在swift中有效地调用API.我试图在其中调用API的代码如下:

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())

    }
}

任何帮助都将不胜感激.非常感谢!

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)
}
    

推荐答案

试试这个示例代码(注意Article中的mods),对我来说效果很好.注意,不要显示您的api密钥,请删除它:

struct ContentView: View {
    @StateObject var newsWebService = NewsWebService()
    var body: some View {
        NewsListView().environmentObject(newsWebService)
    }
}

struct NewsListView: View {
    @EnvironmentObject var newsWebService: NewsWebService
    
    var body: some View {
        List(newsWebService.news?.articles ?? []){ article in  // <-- here
            Text(article.title)
        }
        .task {
            do{
                try await newsWebService.getNews()
            } catch{
                print("---> task error: \(error)")
            }
        }
    }
}

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)
            }
    }
}

struct NewsResponse: Codable {
    let status: String
    let totalResults: Int
    let articles: [Article]
}

struct Article: Codable, Identifiable {
    let id = UUID()
    let source: Source
    let author: String?  
    let title, articleDescription: String
    let url: String
    let urlToImage: String? 
    let publishedAt: String? // <-- here
    let content: String
    
    enum CodingKeys: String, CodingKey {
        case source, author, title
        case articleDescription = "description"
        case url, urlToImage, publishedAt, content
    }
}

struct Source: Codable {
    let id: String?
    let name: String
}

这是假设Constants.url.pokeNews是"https://newsapi.org/v2/everything?q=pokemon&apiKey=YOURKEY"

编辑-1:

如果要使用Articlelet publishedAt: Date?而不是String?,请使用:

 func getNews() async throws {
     let (data, _) = try await URLSession.shared.data(from: Constants.url.pokeNews)
     Task{@MainActor in
         let decoder = JSONDecoder() // <-- here
         decoder.dateDecodingStrategy = .iso8601  // <-- here
         self.news = try decoder.decode(NewsResponse.self, from: data)
     }
 }

Json相关问答推荐

Vegalite中分组条形图中的偏移量问题

当有2个嵌套数组时展平复杂的JSON

(Kotlin)com.google.gson.internal.LinkedTreeMap无法转换为com.example.phonetest2.model.HallData

bash用jq获取第二条JSON记录

Moshi:序列化 List 时出现问题

使用 JQ 获取 JSON 中的替代元素(输出:JSON 对象)

小写嵌套特定键的震动转换

数据清理设计不良的 JSON 数据 - 需要有关最佳策略的建议

Jolt 变换 - 如何用字段值重命名字段?

如何在 Dart 中与多个 map (字典)相交

如何配置spring mvc 3在json响应中不返回null对象?

如何使用法语口音对数组进行 json_encode?

如何使用 gson 调用默认反序列化

在 bash 中将 CSV 转换为 JSON

按 JSON 数据类型 postgres 排序

十六进制格式可以与 JSON 文件一起使用吗?如果是这样,怎么做?

POST:在 url 本身中发送 post 请求

如何从 JSON 响应中提取单个值?

IE10/11 Ajax XHR 错误 - SCRIPT7002:XMLHttpRequest:网络错误 0x2ef3

jq:按属性分组和键