I am trying to draw route between two points but not able to do so beacuese there is nill value in my polypoints.
This is how I am doing it :
Parsing JSON :
if let json : [String:Any] = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]{
if let routes = json["routes"] as? [Any]{
if let overview_polyline = routes[0] as?[String:Any]{
print("overview_polyline\(overview_polyline)")// Getting values till here
if let polyString = overview_polyline["points"] as? String{
//Call this method to draw path on map
self.showPath(polyStr: polyString)
}
}
}
}
Till polystring I am getting values but not getting any value for this line of code if let polyString = overview_polyline["points"] as? String.
Any idea why polyString is nil ?
I have gone through this link to clear the concepts still not able to implement it.
unexpectedly found nil while unwrapping an Optional value
I achieved this by modifying above code to this code. So to parse google api and create a polyline on map, you can use this code, written in swift 3.
if let json : [String:Any] = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]{
let routes = json["routes"] as! NSArray;
print(routes)
self.mapView.clear()
OperationQueue.main.addOperation({
for route in routes {
let routeOverviewPolyline:NSDictionary = (route as! NSDictionary).value(forKey: "overview_polyline") as! NSDictionary
let points = routeOverviewPolyline.object(forKey: "points")
let path = GMSPath.init(fromEncodedPath: points! as! String)
let polyline = GMSPolyline.init(path: path)
polyline.strokeWidth = 3
polyline.map = self.mapView
}
})
}
Related
Does anyone know why I get this error?
func parseData(JSONData: Data){
do{
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONStandard
if let tracks = readableJSON["tracks"] as? JSONStandard{
if let items = tracks["items"]{
for i in 0..<items.count {
let item = items[i] as! JSONStandard //Here I get the error: Ambiguous use of 'subscript(_:)'
let name = item["name"]
names.append(name)
Change following
if let items = tracks["items"]
To
if let items = tracks["items"] as? [JSONSStandard]
Here,
i have source latitude & longitude
in the same way i also have destination latitude & longitude
Now, i want to show the path between these two lat & long's
sourcelatitude = 12.9077869892472
sourcelongitude = 77.5870421156287
print(sourcelatitude!)
print(sourcelongitude!)
destinationlatitude = 12.907809
destinationlongitude = 77.587066
print(destinationlatitude!)
print(destinationlongitude!)
Could any one help me with this
Try this
let origin = "\(12.9077869892472),\(77.5870421156287)"
let destination = "\(12.907809),\(77.587066)"
let url = URL(string: "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)")
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
if(error != nil){
print("error")
}else{
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String : AnyObject]
if json["status"] as! String == "OK"
{
let routes = json["routes"] as! [[String:AnyObject]]
OperationQueue.main.addOperation({
for route in routes
{
let routeOverviewPolyline = route["overview_polyline"] as! [String:String]
let points = routeOverviewPolyline["points"]
let path = GMSPath.init(fromEncodedPath: points!)
let polyline = GMSPolyline(path: path)
polyline.strokeColor = .blue
polyline.strokeWidth = 4.0
polyline.map = mapViewX//Your GMSMapview
}
})
}
}catch let error as NSError{
print(error)
}
}
}).resume()
var aPosition = "30.9621,40.7816"
let bPosition = "26.9621,75.7816"
let urlString = "https://maps.googleapis.com/maps/api/directions/json?origin=\(aPosition)&destination=\(bPosition)&key=\(your google key)"
//let urlString = "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=\(aPosition)&destinations=\(bPosition)&key=AIzaSyCaSIYkkv41RTn5vFLiSoZFlCUhIg-Db5c"
print(urlString)
Alamofire.request(urlString)
.responseJSON { response in
if let array = json["routes"] as? NSArray {
if let routes = array[0] as? NSDictionary{
if let overview_polyline = routes["overview_polyline"] as? NSDictionary{
if let points = overview_polyline["points"] as? String{
print(points)
// Use DispatchQueue.main for main thread for handling UI
DispatchQueue.main.async {
// show polyline
let path = GMSPath(fromEncodedPath:points)
self.polyline.path = path
self.polyline.strokeWidth = 4
self.polyline.strokeColor = UIColor.blue
self.polyline.map = self.mapView
}
}
}
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am having some issues getting the following code to work, any ideas why it doesn't work?
guard let parsedData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments),
let parsedDict = parsedData as? [String:Any],
let stop = parsedDict["Stop"] as? [String:Any],
let name = stop["Name"] as? String,
let latitude = stop["Latitude"] as? String,
let longitude = stop["Longitude"] as? String else
{
print("Something Went Wrong")
return
}
nameArray.append(name)
latArray.append(latitude)
longArray.append(longitude)
However, the following code does work:
if let parsedData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]
{
if let stop = parsedData?["Stop"] as? [String:Any]
{
if let latitude = stop["Latitude"] as? String, let longitude = stop["Longitude"] as? String, let name = stop["Name"] as? String
{
nameArray.append(name)
latArray.append(latitude)
longArray.append(longitude)
}
}
}
EDIT
After reviewing the code, the issue seems to stem from this line:
guard let stop = parsedDict["Stop"] as? [String:Any] else
{
print("Something went wrong")
return
}
When running this I receive "Something went wrong" in the console, however when running
if let stop = parsedData?["Stop"] as? [String:Any]
{
print(stop)
}
I get a valid print of stop.
Running your guard example myself in a playground is successful for me. I would recommend breaking up your guard into multiple logical sections. For example to help you track down your error you could change it to:
//Note: You should not force unwrap data here
guard let parsedData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) else{
print("Serialization error"); return
}
guard
let parsedDict = parsedData as? [String:Any],
let stop = parsedDict["Stop"] as? [String:Any] else {
print("Error casting to dictionary"); return
}
guard
let name = stop["Name"] as? String,
let latitude = stop["Latitude"] as? String,
let longitude = stop["Longitude"] as? String else {
print("Error casting dictionary values"); return
}
//Everything is ok here
I seem to have picked up a few errors since updating to swift 3
// Issue #1
let correctedAddress:String! = self.searchResults![(indexPath as NSIndexPath).row].addingPercentEncoding(withAllowedCharacters: CharacterSet.symbols)
print(correctedAddress)
let url = URL(string: "https://maps.googleapis.com/maps/api/geocode/json?address=\(correctedAddress)&sensor=false")
let task = URLSession.shared.dataTask(with: url!) {
data, response, error in
do {
if data != nil{
let dic = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableLeaves) as! NSDictionary
// Issue #2
let results = dic["results"] as! [String: Any]
let geometry = results["geometry"] as! [String: Any]
let location = geometry["location"] as! [String: Any]
let lat = location["lat"] as! Double
let lon = location["lng"] as! Double
self.delegate.locateWithLongitude(lon, andLatitude: lat)
}
}
catch {
print("Error")
}
}
task.resume()
issue #1:
correctedAddress, as an example, returns value "%51%75%C3%A9%62%65%63%2C%20%43%61%6E%61%64%61". Nevertheless, for some reason the url constant returns nil and causes a crash.
I don't understand why it returns nil. I can replace correctedAddress inside the url with the value %51%75%C3%A9%62%65%63%2C%20%43%61%6E%61%64%61 so the full url is
let url = NSURL(string: "https://maps.googleapis.com/maps/api/geocode/json?address=%51%75%C3%A9%62%65%63%2C%20%43%61%6E%61%64%61&sensor=false") and it works fine.
issue #2:
It crashes just at let results to which i get back the error of Could not cast value of type '__NSArrayI' (0x108bb0c08) to 'NSDictionary' (0x108bb1108).
Try the below code for your Issue#2
let results = dic["results"] as! NSArray
for result in results {
let strObj = result as! NSDictionary
let geometry = strObj["geometry"] as! NSDictionary
let location = geometry["location"] as! NSDictionary
let lat = location["lat"] as! NSNumber
let lon = location["lng"] as! NSNumber
}
For issue#1, try the below code
let valueAtIndex = self.searchResults![(indexPath as NSIndexPath).row].addingPercentEncoding(withAllowedCharacters: CharacterSet.symbols)
guard let correctedAddress = valueAtIndex else { return }
let adrString:String = "https://maps.googleapis.com/maps/api/geocode/json?address=\(correctedAddress)&sensor=false"
let url:URL = URL(string: adrString)!
I had a block of code parsing JSON from the youtube API. The JSON object received is stored in the dictionary and then a sub array of JSON objects items is stored in item. Xcode is giving me an error where it says: "items" is an ambiguous reference to member subscript for JSON and i for item[i].
I read through some posts on stack-overflow addressing similar issues where it said Swift 3 changed the type to [String: AnyObject] but that didn't work for me either.
do
{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! Dictionary<NSObject, AnyObject>
//print(json)
let item: Array<Dictionary<NSObject,AnyObject>> = json["items"] as! Array<Dictionary<NSObject,AnyObject>>
for i in 0 ..< item.count
{
let snippetDict = (item[i] as Dictionary<NSObject, AnyObject>)["snippet"] as! Dictionary<NSObject, AnyObject>
// Initialize a new dictionary and store the data of interest.
var desiredVideoDict = Dictionary<NSObject, AnyObject>()
desiredVideoDict["title"] = snippetDict["title"]
desiredVideoDict["thumbnail"] = ((snippetDict["thumbnails"] as! Dictionary<NSObject, AnyObject>)["default"] as! Dictionary<NSObject, AnyObject>)["url"]
desiredVideoDict["videoID"] = (snippetDict["resourceId"] as! Dictionary<NSObject, AnyObject>)["videoId"]
// Append the desiredPlaylistItemDataDict dictionary to the videos array.
//self.videosArray.append(desiredPlaylistItemDataDict)
// Reload the tableview.
self.tblVideos.reloadData()
Thank you for your time and help.
The standard JSON dictionary has the type [String:Any] in Swift 3.
I recommend to use a type alias for better legibility.
typealias JSONObject = [String:Any]
Now you can write your code this way (I changed also the for loop syntax)
do
{
let json = try JSONSerialization.jsonObject(with: data!, options: []) as! JSONObject
//print(json)
let items = json["items"] as! Array<JSONObject>
for item in items
{
let snippetDict = item["snippet"] as! JSONObject
// Initialize a new dictionary and store the data of interest.
var desiredVideoDict = JSONObject()
desiredVideoDict["title"] = snippetDict["title"]
desiredVideoDict["thumbnail"] = ((snippetDict["thumbnails"] as! JSONObject)["default"] as! JSONObject)["url"]
desiredVideoDict["videoID"] = (snippetDict["resourceId"] as! JSONObject)["videoId"]
// Append the desiredPlaylistItemDataDict dictionary to the videos array.
//self.videosArray.append(desiredPlaylistItemDataDict)
// Reload the tableview.
}
self.tblVideos.reloadData()
...
mutableContainers is not needed at all.
This worked for me:
do
{
let json = try JSONSerialization.jsonObject(with: data , options: .mutableContainers) as! Dictionary<String, AnyObject>
//print(json)
let item = json["items"] as! Array<Dictionary<String,AnyObject>>
for i in 0 ..< item.count
{
let snippetDict = item[i]["snippet"] as! Dictionary<String, AnyObject>
// Initialize a new dictionary and store the data of interest.
var desiredVideoDict = Dictionary<String, AnyObject>()
desiredVideoDict["title"] = snippetDict["title"]
desiredVideoDict["thumbnail"] = ((snippetDict["thumbnails"] as! Dictionary<String, AnyObject>)["default"] as! Dictionary<String, AnyObject>)["url"]
desiredVideoDict["videoID"] = (snippetDict["resourceId"] as! Dictionary<String, AnyObject>)["videoId"]
// Reload the tableview.
self.tblVideos.reloadData()
}
}catch{
print("parse error")
}