Want to view json metadata

断了今生、忘了曾经 提交于 2019-12-02 12:34:06

The main error is that the value for key 5. Exchange Rate is String not Float and the code crashes reliably when being force unwrapped.

In Swift 4 the Decodable protocol is much more convenient than a dictionary.

Create two structs. The ExchangeRate struct contains a computed property floatRate to return the Float value

struct Root : Decodable {
    let exchangeRate : ExchangeRate
    private enum  CodingKeys: String, CodingKey { case exchangeRate = "Realtime Currency Exchange Rate" }
}

struct ExchangeRate : Decodable {

    let fromCode, fromName, toCode, toName, rate : String
    let lastRefreshed, timeZone : String

    private enum  CodingKeys: String, CodingKey {
        case fromCode = "1. From_Currency Code"
        case fromName = "2. From_Currency Name"
        case toCode = "3. To_Currency Code"
        case toName = "4. To_Currency Name"
        case rate = "5. Exchange Rate"
        case lastRefreshed = "6. Last Refreshed"
        case timeZone = "7. Time Zone"
    }

    var floatRate : Float {
        return Float(rate) ?? 0.0
    }
}

Then make the download function more versatile by passing from and to currency as parameters. This version uses the JSONDecoder and returns either the ExchangeRate instance or the Error

func downloadRate(from: String, to: String, completionHandler: @escaping (ExchangeRate?, Error?) -> Void) {

    let urlString = "https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=\(from)&to_currency=\(to)&apikey=NP3M8LL62YJDO0YX"
    let task = URLSession.shared.dataTask(with: URL(string: urlString)!, completionHandler: { data, response, error in
        if error != nil {
            completionHandler(nil, error!)
        } else {
            do {
                let result = try JSONDecoder().decode(Root.self, from: data!)
                completionHandler(result.exchangeRate, nil)
            } catch {
                completionHandler(nil, error)
            }
        }
    })
    task.resume()
}

and use it

func usdQUotesRequest() {

  USDClient().downloadRate(from:"USD", to: "EUR") { exchangeRate, error in

    if let exchangeRate = exchangeRate {
        self.usdtoeurquote = exchangeRate.floatRate
        DispatchQueue.main.async {
            self.stopActivityIndicator()
            self.Refresh.isEnabled = true
        }
    } else {
        DispatchQueue.main.async {
            self.displayAlert("Unable to Retrieve Latest Conversion Rates", message: "\(error!)")
            self.stopActivityIndicator()
            self.Refresh.isEnabled = true
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!