ListView 的 Swift JSON 嵌套输出

问题描述 投票:0回答:1

我正在尝试显示结果的内容。 数据以 JSON 数组形式返回。 我创建了一个视图模型“股票”并想要访问“结果”。目前可以编译,但数据没有显示。

我们将非常感谢您的帮助。

import SwiftUI
struct Stocks: Hashable, Codable{
    var results: [Results]
    var status: String
    
    struct Results: Hashable, Codable{
        var ticker: String
        var name: String
        var market: String
        var locale: String
        var primary_exchange: String
        var type: String
        var active: Bool
        var currency_name: String
        var cik: String
        var composite_figi: String
        var share_class_figi: String
        var last_update_utc: String
    }
}


class ViewModel: ObservableObject{
    @Published var stocks: [Stocks] = []
    func fetch(){
        guard let url = URL(string: "https://api.polygon.io/v3/reference/tickers?market=stocks&active=true&apiKey=<apikey>") else{return}
        
        let task = URLSession.shared.dataTask(with: url) {[weak self]data, _, error in
            guard let data = data, error == nil else{
                return
            }
            // Convert JSON
            do{
                let stocks = try JSONDecoder().decode([Stocks].self, from: data)
                DispatchQueue.main.async{
                    self?.stocks = stocks
                }
               
            }
            catch{
                print(error)
            }
        }
        task.resume()
    }
}

struct ContentView: View {
    @StateObject var viewModel = ViewModel()

    
    var body: some View {
        NavigationView{
            List{
                ForEach(viewModel.stocks, id: \.self){resu in
                    ForEach(resu.results, id: \.self){st in
                        Text(st.currency_name)
                    }
                }
                
            }
        }.navigationTitle("Stocks")
        .onAppear{
            viewModel.fetch()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

这是 Response 对象:

{
    "results": [
        {
            "ticker": "A",
            "name": "Agilent Technologies Inc.",
            "market": "stocks",
            "locale": "us",
            "primary_exchange": "XNYS",
            "type": "CS",
            "active": true,
            "currency_name": "usd",
            "cik": "0001090872",
            "composite_figi": "BBG000C2V3D6",
            "share_class_figi": "BBG001SCTQY4",
            "last_updated_utc": "2022-12-20T00:00:00Z"
        },
        {
            "ticker": "AA",
            "name": "Alcoa Corporation",
            "market": "stocks",
            "locale": "us",
            "primary_exchange": "XNYS",
            "type": "CS",
            "active": true,
            "currency_name": "usd",
            "cik": "0001675149",
            "composite_figi": "BBG00B3T3HD3",
            "share_class_figi": "BBG00B3T3HF1",
            "last_updated_utc": "2022-12-20T00:00:00Z"
        },

我创建了一个视图模型“Stocks”并想要访问“结果”。目前可以编译,但数据没有显示。

ios json swift listview
1个回答
1
投票

结构的命名非常令人困惑。

根据 JSON,您将收到 one 根对象,其中包含键

Stock
results
(应该以单数形式命名)对象数组。

并且有一个结构体成员

last_update_utc
与键
last_updated_utc
不匹配。

以这种方式命名您的结构,我将结构成员重命名为驼峰命名法和常量 (

let
),您可以使用
lastUpdatedUtc
策略将
Date
解码为
.iso8601

struct Response: Hashable, Decodable {
    let results: [Stock]
    let status: String
    
    struct Stock: Hashable, Decodable {
        let ticker: String
        let name: String
        let market: String
        let locale: String
        let primaryExchange: String
        let type: String
        let active: Bool
        let currencyName: String
        let cik: String
        let compositeFigi: String
        let shareClassFigi: String
        let lastUpdatedUtc: Date
    }
}

并解码 JSON

class ViewModel: ObservableObject{
    @Published var stocks: [Response.Stock] = []
    func fetch() {
        guard let url = URL(string: "https://api.polygon.io/v3/reference/tickers?market=stocks&active=true&apiKey=<apikey>") else{return}
        
        let task = URLSession.shared.dataTask(with: url) {[weak self] data, _, error in
            if let error { print(error); return }
            // Convert JSON
            do{
                let decoder = JSONDecoder()
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                decoder.dateDecodingStrategy = .iso8601
                let response = try decoder.decode(Response.self, from: data!)
                DispatchQueue.main.async {
                    self?.stocks = response.results
                }
               
            }
            catch{
                print(error)
            }
        }
        task.resume()
    }
}

我什至建议使用

async/await

@MainActor
class ViewModel: ObservableObject{
    @Published var stocks: [Response.Stock] = []
    
    func fetch() {
        guard let url = URL(string: "https://api.polygon.io/v3/reference/tickers?market=stocks&active=true&apiKey=<apikey>") else{return}
        Task {
            do {
                let (data, _) = try await URLSession.shared.data(from: url)
                let decoder = JSONDecoder()
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                decoder.dateDecodingStrategy = .iso8601
                let response = try decoder.decode(Response.self, from: data)
                self.stocks = response.results
            } catch {
                print(error)
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.