I am learning Swift and trying to get elevation data based on coordinates from the Open Elevation API.
I found a code to make the request and decode the data using structs.
My problem is that the API result includes the information in an array:
{"results": [{"latitude": 41.161758, "longitude": -8.583933, "elevation": 117}]}
What I have been able to program so far does save the data as an array in json.results, but only with one index including all of the data:
[API.MyResult(latitude: 41.16176, longitude: -8.583933, elevation: 117)]
("API" is the name of the file)
Here is my code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let url = "https://api.open-elevation.com/api/v1/lookup?locations=41.161758,-8.583933"
getData(from: url)
}
private func getData(from url: String){
let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: {data, response, error in
guard let data = data, error == nil else {
print("error")
return
}
var result: Response?
//print(result)
do{
result = try JSONDecoder().decode(Response.self, from: data)
}
catch{
print(error.localizedDescription)
}
guard let json = result else {
return
}
print(json.results)
//print(json.results.latitude)
//print(json.results.longitude)
//print(json.results.elevation)
})
task.resume()
}
}
struct Response: Codable {
let results: [MyResult]
}
struct MyResult: Codable {
let latitude: Float
let longitude: Float
let elevation: Int
}
Trying to print out json.results.latitude leads to the error
"Value of type '[MyResult]' has no member 'latitude'"
I assume at some point, a variable has to be defined as an array.
What needs to be changed here?
CodePudding user response:
result
is indeed a single object, but the property results
is an array (multiple objects).
A slightly different naming avoids the confusion.
Notes:
Never print literal
"error"
orerror.localizedDescription
in a Decoding context, always print theerror
instance.Proceed to parse the result in the
do
scopeprivate func getData(from url: String){ guard let url = URL(string: url) else { print("Bad URL", url); return } let task = URLSession.shared.dataTask(with: url) {data, _, error in if let error = error { print(error); return } do { let response = try JSONDecoder().decode(Response.self, from: data!) for result in response.results { print(result.latitude) print(result.longitude) print(result.elevation) } } catch { print(error) } } task.resume() }