首页 > 解决方案 > 尝试从结构访问 JSON 数据时出现索引超出范围错误

问题描述

我正在尝试从 IEX 财务 API 获取股票数据,我需要的一切都可以很好地输出到控制台,但是我在尝试使用该数据插入我的表格视图时遇到了问题。

这是API url,这是可读格式的 JSON

这些是我设置的结构

struct Welcome: Decodable {
    let aapl, fb, msft, tsla, goog: Aapl

    enum CodingKeys: String, CodingKey {
        case aapl = "AAPL"
        case fb = "FB"
        case msft = "MSFT"
        case tsla = "TSLA"
        case goog = "GOOG"
    }
}

struct Aapl: Decodable {
    let quote: Quote
    let news: [News]
}

struct Quote: Decodable {
    let symbol: String
    let companyName: String
    let latestPrice: Double
}

struct News: Decodable {
    let url: String
    let image: String
}

这是获取数据的方式:

fetchData(url: stockApiUrl) { (result: FetchResult<Welcome>) -> (Void) in
    switch result {
    case .success(let object): self.stockData = [object]
        print("stockData: \n\n\(self.stockData)")
    case .failure(let error):
        print("Error decoding JSON: \n\n\(error)")
    }
    DispatchQueue.main.async {
        self.tableView.reloadData()
    }
}

并将数据传入

var stockData = [Welcome]()

使用现在的代码,它输出公司所需的所有数据,但我对如何访问所有公司数据感到困惑,因此我可以单独抓取每一块(companyNamelatestPrice等),以便我可以显示它们在表格视图中。

例如,在我的cellForRowAt表格视图方法中,我试图将 设置companyName为标签,但是使用let quotes = stockData[indexPath.row]给了我一个索引超出范围错误,所以我不能再使用类似cell.companyNameLabel = quotes[indexPath.row].companyName.

我想知道是否需要重组我的结构(尽管我将我的代码与来自 quicktype.io 的建议代码进行了比较,并且它是相同的),或者重新处理其他东西。

感谢您的任何指导!

编辑:

numberOfRows方法:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
        return stockData.count
    } else if section == 1 && fetchingMore {
        return 1
    }
    return 0
}

fetchData功能:

func fetchData<T: Decodable>(url: URL, completion: @escaping (FetchResult<T>) -> (Void)) {

    URLSession.shared.dataTask(with: url) { (data, response, error) in

        guard let data = data else {completion(.failure(error!)); return}

        do {
            //let object = try JSONDecoder().decode(T.self, from: data)
            let object = try? JSONDecoder().decode([String:Aapl].self,from: data)
            completion(.success(object))
        } catch {
            completion(.failure(error))
        }
    }.resume()
}

标签: iosjsonswiftstruct

解决方案


你可以做

 var welcomes:[String:Aapl]! 

 welcomes = try? JSONDecoder().decode([String:Aapl].self,from:jsonData)

然后在里面使用这个numberOfRowsInSection

return welcomes.keys.count

和里面cellForRowAt

let item = welcomes[welcomes.keys[indexPath.row]]!.quote.companyName

如果您不关心排序,请使用它


推荐阅读