I am using google places api to get latitude and longitude , but not able to parse dictionary. I am using following code
let lat = ((((dic["results"] as! AnyObject).value(forKey: "geometry") as AnyObject).value(forKey: "location") as AnyObject).value(forKey: "lat") as AnyObject).object(0) as! Double
Error: Cannot call value of non-functioning type 'Any?!'
I have also checked with nsdictionary instead of Anyobject but didn't worked . Can any one know how to properly get lat from above code.
Responce :
{
results = (
{
"address_components" = (
{
"long_name" = Palermo;
"short_name" = Palermo;
types = (
locality,
political
);
},
{
"long_name" = "Province of Palermo";
"short_name" = PA;
types = (
"administrative_area_level_2",
political
);
},
{
"long_name" = Sicily;
"short_name" = Sicily;
types = (
"administrative_area_level_1",
political
);
},
{
"long_name" = Italy;
"short_name" = IT;
types = (
country,
political
);
}
);
"formatted_address" = "Palermo, Italy";
geometry = {
bounds = {
northeast = {
lat = "38.219548";
lng = "13.4471566";
};
southwest = {
lat = "38.0615392";
lng = "13.2674205";
};
};
location = {
lat = "38.1156879";
lng = "13.3612671";
};
"location_type" = APPROXIMATE;
viewport = {
northeast = {
lat = "38.2194316";
lng = "13.4471566";
};
southwest = {
lat = "38.0615392";
lng = "13.2674205";
};
};
};
"place_id" = ChIJmdBOgcnoGRMRgNg7IywECwo;
types = (
locality,
political
);
}
);
status = OK;
}
You have to parse the JSON in multiple steps, for clarity I'd recommend to use a type alias:
typealias JSONDictionary = [String:Any]
let results = dic["results"] as? [JSONDictionary] {
for result in results {
if let geometry = result["geometry"] as? JSONDictionary,
let location = geometry["location"] as? JSONDictionary {
if let lat = location["lat"] as? Double,
let lng = location["lng"] as? Double {
print(lat, lng)
}
}
}
}
A few rules in Swift :
NSDictionary
/ NSArray
at all unless you have absolutely no choice.[String:Any]
, a JSON array [[String:Any]]
.Any
types down as specific as possible.Kristijan's answer is somewhat correct, though it ignores a lot of important syntax and optional type casting. Assuming somewhere in your code you are making the actual API call:
class SomeClass {
func getLocationData() {
//do your api call stuff here and get "result"
let location: Location? = Location(json: result as? [String:Any])
}
}
You can handle the response in some way, perhaps with a struct:
struct Location {
var lat: Double
var long: Double
init(lat: Double, long: Double) {
self.lat = lat
self.long = long
}
init?(json: [String:Any]?) {
guard let results = json?["results"] as? [Any],
let first = results[0] as? [String:Any],
let geometry = first["geometry"] as? [String:Any],
let location = geometry["location"] as? [String:Any],
let latitude = location["lat"] as? Double,
let longitude = location["lng"] as? Double else {
return nil
}
self.lat = latitude
self.long = longitude
}
}
The point in the struct initializer is using conditional unwrapping to type cast your JSON response object's respective members to their appropriate types.
Note that this can vary significantly based on the actual JSON object you are receiving from the API. It would be helpful if you could post the actual JSON response in raw text in addition to the Swift code you've already attempted to write to parse it. My response does the best it can based on the information you provided. I could probably write something with a higher degree of confidence were you to supply the raw JSON object from your API response.
Edit: Following is a Playground snippet which retrieves and parses the result from the Google Places API
import PlaygroundSupport
import Foundation
PlaygroundPage.current.needsIndefiniteExecution = true
struct Location {
var lat: Double
var long: Double
init(lat: Double, long: Double) {
self.lat = lat
self.long = long
}
init?(json: [String:Any]?) {
guard let results = json?["results"] as? [Any],
let first = results[0] as? [String:Any],
let geometry = first["geometry"] as? [String:Any],
let location = geometry["location"] as? [String:Any],
let latitude = location["lat"] as? Double,
let longitude = location["lng"] as? Double else {
return nil
}
self.lat = latitude
self.long = longitude
}
}
func getLocationData() {
let base = "https://maps.googleapis.com/maps/api/geocode/json"
let args = [
"address=%50%61%6C%65%72%6D%6F%2C%20%50%72%6F%76%69%6E%63%65%20%6F%66%20%50%61%6C%65%72%6D%6F%2C%20%49%74%61%6C%79",
"sensor=false",
]
let urlStr = "\(base)?\(args.joined(separator: "&"))"
guard let url = URL(string: urlStr) else { return }
var request = URLRequest(url: url)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request,
completionHandler: { (data, response, error) -> Void in
guard let jsonData = data else { return }
if let jsonResult = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as? [String:Any] {
let location: Location? = Location(json: jsonResult)
print("Location: \(location?.lat), \(location?.long)")
}
}
).resume()
}
getLocationData()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With