I'm trying to implement a stock API. I have a JSON example:
{
"Meta Data": {
"1. Information": "Daily Prices (open, high, low, close) and Volumes",
"2. Symbol": "DAI.DEX",
"3. Last Refreshed": "2022-04-05",
"4. Output Size": "Full size",
"5. Time Zone": "US/Eastern"
},
"Time Series (Daily)": {
"2022-04-05": {
"1. open": "64.4900",
"2. high": "64.8200",
"3. low": "62.6200",
"4. close": "62.9600",
"5. volume": "3425810"
},
"2022-04-04": {
"1. open": "63.9900",
"2. high": "64.5400",
"3. low": "62.8100",
"4. close": "64.2600",
"5. volume": "2538008"
}
}
I'm trying to display the latest price so I always need the first element in Time Series Daily. In this example 2022-04-05. The list goes on for 20 years. I tried this:
var latestClose: String {
timeSeriesDaily.first?.value.close ?? ""
}
But every time I rerun the app it displays different values and not constantly the first value.
Here my Code:
struct StockData: Codable {
var metaData: MetaData
var timeSeriesDaily: [String: TimeSeriesDaily]
var latestClose: String {
timeSeriesDaily.first?.value.close ?? ""
}
private enum CodingKeys: String, CodingKey {
case metaData = "Meta Data"
case timeSeriesDaily = "Time Series (Daily)"
}
struct MetaData: Codable {
let information: String
let symbol: String
let lastRefreshed: String
let outputSize: String
let timeZone: String
private enum CodingKeys: String, CodingKey {
case information = "1. Information"
case symbol = "2. Symbol"
case lastRefreshed = "3. Last Refreshed"
case outputSize = "4. Output Size"
case timeZone = "5. Time Zone"
}
}
struct TimeSeriesDaily: Codable {
var open: String
var high: String
var low: String
var close: String
var volume: String
private enum CodingKeys: String, CodingKey {
case open = "1. open"
case high = "2. high"
case low = "3. low"
case close = "4. close"
case volume = "5. volume"
}
}
}
CodePudding user response:
There is no first element because the object is a dictionary which is unordered by definition.
To get the most recent item you have to get the dictionary keys
(this returns an array) and sort them descending. The most recent date is the first item.
var latestClose: String {
guard let mostRecentDate = timeSeriesDaily.keys.sorted(by: >).first else { return "" }
return timeSeriesDaily[mostRecentDate]!.close
}