首页 > 解决方案 > 从 JSON 数据 SwiftUI 更新列表

问题描述

我很难理解 JSON 数据应该如何在 SwiftUI 的列表中更新。我正在从 NewsAPI.org 获取数据,我的列表和详细视图工作得很好。我试图弄清楚当我的 json 数据更改时如何使列表保持最新,但数据仍然过时。我仍然是 swift 的初学者,所以如果我犯了错误,任何帮助将不胜感激。

已更新尝试使用 combine 与相同的结果,过时的数据

新数据类

class NewsData: ObservableObject {
    var objectWillChange = PassthroughSubject<NewsData, Never>()
    
    @Published var articles = [Article]() {
        willSet {
            objectWillChange.send(self)
        }
    }
    
    init() {
        guard let url = URL(string: "http://newsapi.org/v2/top-headlines?country=us&apiKey=API_KEY") else { return }
        let request = URLRequest(url: url)
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let response = try? JSONDecoder().decode(News.self, from: data) {
                    DispatchQueue.main.async() {
                        self.articles = response.articles
                    }
                }
            }
        }
        .resume()
    }
    
    /*
    init() {
        URLSession.shared
            .dataTaskPublisher(for: URLRequest(url: URL(string: "http://newsapi.org/v2/top-headlines?country=us&apiKey=API_KEY")!))
            .map(\.data)
            .decode(type: News.self, decoder: JSONDecoder())
            .receive(on: DispatchQueue.main)
            .sink(receiveCompletion: { completion in
                switch completion {
                case .finished:
                    break
                case .failure(let error):
                    print(error.localizedDescription)
                }
            }, receiveValue: { data in
                self.articles = data.articles
            })
            .store(in: &self.cancellables)
    }
    */
    
    /*
    init() {
        load()
    }
    
    func load() {
        guard let url = URL(string: "http://newsapi.org/v2/top-headlines?country=us&apiKey=API_KEY") else { return }
        let request = URLRequest(url: url)
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let response = try? JSONDecoder().decode(News.self, from: data) {
                    DispatchQueue.main.async() {
                        self.articles = response.articles
                    }
                }
            }
        }
        .resume()
    }
    */
}

我的数据老班

struct News : Codable {
    var articles : [Article]
}

struct Article : Codable {
    let description : String?
    let title : String?
    let author: String?
    let source: Source
    let content: String?
    let publishedAt: String?
}

struct Source: Codable {
    let name: String?
}

class NewsData: ObservableObject {
   @Published var news: News = News(articles: [])
    
    init() {
        load()
    }
    
    func load() {
        guard let url = URL(string: "http://newsapi.org/v2/top-headlines?country=us&apiKey=API_KEY_HERE") else { return }
        let request = URLRequest(url: url)
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let response = try? JSONDecoder().decode(News.self, from: data) {
                    DispatchQueue.main.async() {
                        self.news = response
                    }
                }
            }
        }
        .resume()
    }
}

我的内容视图

func relativeDate(date: String) -> String {
    let formatter = RelativeDateTimeFormatter()
    let dateFormatter = ISO8601DateFormatter()
    return formatter.localizedString(for: dateFormatter.date(from: date) ?? Date(), relativeTo: Date())
}


struct ContentView: View {
    @ObservedObject var news: NewsData
    
    var body: some View {
        NavigationView {
            List(news.news.articles , id: \.title) { article in
                VStack (alignment: .leading, spacing: 5){
                    Text(article.title ?? "")
                        .fontWeight(.bold)
                        .font(.subheadline)
                        .lineLimit(1)
                    Text(article.description ?? "")
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                        .lineLimit(1)
                   Text(relativeDate(date: article.publishedAt ?? ""))
                         .font(.subheadline)
                         .foregroundColor(.secondary)
                }
            }
            .navigationTitle("News")
        }
    }
}

标签: iosswiftuicombineswiftui-list

解决方案


推荐阅读