首页 > 解决方案 > How to store multiple back dates in a Swift Struct?

问题描述

I would like to store the previous 4 days closing event in an individual struct so that i can make reference to them later on in the program. How would you go about storing the the closing event for each 4 days after sorting them from the JSON API.

The code below has sorted the previous 4 days but i am unable to figure how to store each day to use them separately

class DailyViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    let jsonUrlString = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo"

    let urlObj = URL(string: jsonUrlString)

    URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in
        guard let data = data else { return }
        do {
            let forex = try JSONDecoder().decode(Root.self, from: data)

            let sortedKeys = forex.timeSeriesDaily.keys.sorted(by: >)
            let requestedKeys = sortedKeys.prefix(4)
            var requestedPrices = [String:Forex]()
            requestedKeys.forEach{ requestedPrices[$0] = forex.timeSeriesDaily[$0] }
            print(requestedPrices)
            print()
        } catch {
            print(error)
        }

        }.resume()

}

struct Root: Codable {
    let metaData: [String: String]
    let timeSeriesDaily: [String:Forex]

    enum CodingKeys: String, CodingKey {
        case timeSeriesDaily = "Time Series (Daily)"
        case metaData = "Meta Data"
    }
}

struct Forex: Codable {
    let open, high, low, close: String

    enum CodingKeys: String, CodingKey {
        case open = "1. open"
        case high = "2. high"
        case low = "3. low"
        case close = "4. close"


    }
}

}

标签: iosjsonswiftstructcodable

解决方案


One way is to create a struct with four properties for this and add a specific init that takes an array

struct LastFour {
    var close1: String
    var close2: String
    var close3: String
    var close4: String

    init?(_ closes: [String]) {
        guard closes.count >= 4 else {
            return nil
        }
        close1 = closes[0]
        close2 = closes[1]
        close3 = closes[2]
        close4 = closes[3]
    }
}

and then use map when initialising the struct from the dictionary

let lastFour = LastFour(requestedPrices.values.map {$0.close})

Note that the init is optional and returns nil in case the array is to short, another option could be to throw an error for instance.

Maybe a more flexible solution would be to use an array internally in the struct and then access the data via a method or perhaps computed properties

struct LastFour {
    private var closeEvents: [String]

    func close(at index: Int) -> String {

    }
}

This would of course require similar code for init and checking the correct size but it would be easier to change if more or less elements are needed


推荐阅读