arrays - Swift + macOS + Xcode:从 ContentView 访问在类中创建的键值对数组
问题描述
我编写了一些代码,成功地将 JSON 文件读入我认为是一个键值对数组,每个键有 5 个值。JSON 文件在创建类的过程中被读入,并且似乎可以工作。在 ContentView 中,我希望能够单步执行键(即日期)和值,可能使用 ForEach 循环。不幸的是,我无法从 ContentView 访问键值对数组。类中的打印语句打印出我所期望的。在 ContentView 中,arrayname.count 返回 0。我想我忽略了一些简单的事情,但有时当你看一些东西太久时,你会错过显而易见的事情。如果有人能指出我正确的方向,将不胜感激。
ForEach 是我尝试确定如何访问 vooData 的各个成员的方式,例如日期,它是键,或特定值,例如关闭。
下面是我的测试代码。问候,克里斯
我的 JSON 文件示例和 ReadData 类中 print 语句的结果如下所示。
{
"Meta Data": {
"1. Information": "Daily Prices (open, high, low, close) and Volumes",
"2. Symbol": "VOO",
"3. Last Refreshed": "2021-09-22",
"4. Output Size": "Full size",
"5. Time Zone": "US/Eastern"
},
"Time Series (Daily)": {
"2021-09-22": {
"1. open": "402.1700",
"2. high": "405.8500",
"3. low": "401.2600",
"4. close": "403.9000",
"5. volume": "5979811"
},
Stock(timeSeriesDaily: [
"2011-07-22": ReadJSONData.TimeSeriesDaily
(Open: "61.5000",
High: "61.6000",
Low: "61.2000",
Close: "61.5500",
Volume: “180400"
),
"2014-06-18": ReadJSONData.TimeSeriesDaily
(
Open: "178.5900",
High: "179.9700",
Low: "178.1700",
Close: "179.8700",
Volume: “501900"
),
"2015-09-18": ReadJSONData.TimeSeriesDaily
(
Open: "180.4100",
High: "182.0400",
Low: "179.6900",
Close: "180.1300",
Volume: “3205186"
)
])
import SwiftUI
struct Stock: Codable {
let timeSeriesDaily: [String: TimeSeriesDaily]
enum CodingKeys: String, CodingKey {
case timeSeriesDaily = "Time Series (Daily)"
}
}
struct TimeSeriesDaily: Codable {
let Open, High, Low, Close: String
let Volume: String
enum CodingKeys: String, CodingKey {
case Open = "1. open"
case High = "2. high"
case Low = "3. low"
case Close = "4. close"
case Volume = "5. volume"
}
}
class ReadData {
//class ReadData: ObservableObject {
// @Published var tmpData = [Stock]()
var tmpData : [Stock] = []
init() {
loadData()
}
func loadData() {
guard let url = Bundle.main.url(forResource: "VOO", withExtension: "json")
else {
print("Json file not found")
return
}
let data = try? Data(contentsOf: url)
let tmpData = try? JSONDecoder().decode(Stock.self, from: data!)
print(tmpData!)
}
}
struct ContentView: View {
// @ObservedObject var vooData = ReadData()
let readClass = ReadData()
@State var vooData : [Stock] = ReadData().tmpData
var body: some View {
VStack{
Text("Hello, world!")
.padding()
.frame(width: 600, height: 400, alignment: .center)
.onAppear(perform: {
print(vooData.count)
})
}
}
}
解决方案
您包含的 JSON 不是真正有效的。我假设它实际上看起来像这样:
{
"Time Series (Daily)": {
"2021-09-22": {
"1. open": "402.1700",
"2. high": "405.8500",
"3. low": "401.2600",
"4. close": "403.9000",
"5. volume": "5979811"
}
}
}
如果是这种情况,那么您可以对您的代码进行一些细微的改动并让它工作。
看起来您最初尝试使用
ObservableObject
- 这就是您应该使用的。在您的原始代码中,您使用
let tmpData =
但从未设置self.tmpData
使用
do/try/catch
而不是try?
更可取,因为如果发生错误,您实际上可以打印错误。目前尚不清楚您要显示的确切内容,但我提供了一个
ForEach
将字典转换为键/值对然后显示开盘价的示例。
struct TimeSeriesDaily: Codable {
let Open, High, Low, Close: String
let Volume: String
enum CodingKeys: String, CodingKey {
case Open = "1. open"
case High = "2. high"
case Low = "3. low"
case Close = "4. close"
case Volume = "5. volume"
}
}
class ReadData: ObservableObject {
@Published var tmpData = Stock(timeSeriesDaily: [:])
init() {
loadData()
}
func loadData() {
guard let url = Bundle.main.url(forResource: "VOO", withExtension: "json")
else {
print("Json file not found")
return
}
do {
let data = try Data(contentsOf: url)
self.tmpData = try JSONDecoder().decode(Stock.self, from: data)
print(self.tmpData)
} catch {
print(error)
}
}
}
struct ContentView: View {
@ObservedObject var vooData = ReadData()
var body: some View {
VStack{
ForEach(vooData.tmpData.timeSeriesDaily.map { ($0.key,$0.value) }, id: \.0) { keyValuePair in
VStack {
Text(keyValuePair.0)
Text("Open: \(keyValuePair.1.Open)")
}
}
}
}
}
推荐阅读
- flutter - 处理方法调用失败;java.lang.IllegalArgumentException:给定字符串为空或为空
- sql - 当它们报告为空时如何替换/连接同一个表中的两个值?
- cupy - 分析时:什么是 API 调用:cupy 中的 cuLaunchKernel
- azure-web-app-service - 为 php web 应用程序创建 azure webapp
- javascript - React/Redux - 添加元素而不是替换状态
- python - 在多个条件下分配对象侧标签
- php - PHP 从 MySQL 表中为每个不同的用户获取 MAX 值
- python - Python中关于动画的简单问题
- intellij-idea - 在 IdeaVim 中移动拆分窗口
- javascript - data-live-search="true" 不适用于多个条目,但适用于第一个条目