Google maps on Swift 4 - swift

Im building an app with google maps, and i would like to show a route between 2 static points
I was folling this tutorial but i can't make it yet, for some reason it dont show the route.
I dont want to make an dinamic route i just want it from two point that i´ve define
here's some code
GMSServices.provideAPIKey("MY API KEY")
let camera = GMSCameraPosition.camera(withLatitude: 19.0660043, longitude: -98.12050499999998, zoom: 18.0)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = mapView
var source = CLLocationCoordinate2DMake(19.060914, -98.125935)
var destination = CLLocationCoordinate2DMake(19.1660043, -98.13000)
plx help

You need to create a path first and then use that path to create a polyline
let path = GMSMutablePath()
path.add(source)
path.add(destination)
let polyline = GMSPolyline(path: path)
polyline.strokeColor = UIColor.red
polyline.strokeWidth = 3.0
polyline.map = self.map

Related

can I use Google maps and places in xcode, and can I customize the icons?

I want to use google maps and places on my IOS application.
Is it even possible? and if so, can I customize the icons inside google maps?
You should read and follow this link for integration :
https://developers.google.com/maps/documentation/ios-sdk/start
And for custom marker follow the link :
google maps iOS SDK: custom icons to be used as markers
its something like this :
let marker = GMSMarker()
// I have taken a pin image which is a custom image
let markerImage = UIImage(named: "mapMarker")!.withRenderingMode(.alwaysTemplate)
//creating a marker view
let markerView = UIImageView(image: markerImage)
//changing the tint color of the image
markerView.tintColor = UIColor.red
marker.position = CLLocationCoordinate2D(latitude: 28.7041, longitude: 77.1025)
marker.iconView = markerView
marker.title = "New Delhi"
marker.snippet = "India"
marker.map = mapView
//comment this line if you don't wish to put a callout bubble
mapView.selectedMarker = marker

Google Maps iOS is not allowing custom map marker image

I am using the Google Maps SDK for iOS - https://developers.google.com/maps/documentation/ios-sdk/marker#use_the_markers_icon_property
Combined with the Maps SDK for iOS Utility Library https://developers.google.com/maps/documentation/ios-sdk/utility/kml-geojson#render-kml-data
I am trying to use the utility library to render a kml file on a map. It mostly works, however the custom icons for the markers are not loading. The markers with their titles, snippets, and locations all load correctly. The only thing that does not work is the custom icon for the marker.
Originally, I thought it was an issue with the utility library, so I spent some time trying to write my own code to go through the kml file and add the custom markers myself. However, before I got too far I noticed that even when I try to add a basic marker with a custom icon, I cannot. This led me to believe it was an issue not with the utility library but with the Maps SDK for iOS. I've tried moving the folder that the image is in, and making sure that the code can see the path to the images, but I cannot get it to work.
This is the code that I have in my project
let path = Bundle.main.path(forResource: testFile, ofType: "kml")
let url = URL(fileURLWithPath: path!)
let kmlParser = GMUKMLParser(url: url)
kmlParser.parse()
let camera = GMSCameraPosition.camera(withLatitude: lat, longitude: long, zoom: zoom)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.mapType = GMSMapViewType.terrain
mapView.isMyLocationEnabled = true
mapView.settings.zoomGestures = true
mapView.settings.myLocationButton = true
let renderer = GMUGeometryRenderer(map: mapView, geometries: kmlParser.placemarks, styles: kmlParser.styles, styleMaps: kmlParser.styleMaps)
renderer.render()
This also does not work
let position = CLLocationCoordinate2D(latitude: lat, longitude: long)
let marker = GMSMarker(position: position)
marker.title = "Test"
marker.icon = UIImage(named: "icon-1")
marker.map = mapView
Thanks in advance for any help
I haven't figured out why the utils library wasn't working, but I did come up with my own fix. It's horrible, but I can come back and make it better later after we've finished adding all the other necessary features to the app and can focus on cleaning up the code .
First, I made a new array of placemarks that had everything except the map markers. I then used this array of placemarks instead of kmlParser.placemarks, so that everything else could be added by the utility library.
//Removing markers without icons
var myIndex = 0
var removed = [GMUGeometryContainer]()
for mark in kmlParser.placemarks{
if(mark.geometry.type != "Point"){
removed.append(kmlParser.placemarks[myIndex])
}
myIndex += 1
}
let renderer = GMUGeometryRenderer(map: mapView, geometries: removed, styles: kmlParser.styles, styleMaps: kmlParser.styleMaps)
renderer.render()
After that, I made my own horrible horrible method that reads the kml file again, and only picks out the placemarks and styles for them and returns an array of Markers.
func addMarkers(fileName:String) -> [GMSMarker]{
var markers = [GMSMarker]()
if let path = Bundle.main.path(forResource: fileName, ofType: "kml"){
do{
let data = try String(contentsOfFile: path, encoding: .utf8)
let myStrings = data.components(separatedBy: .newlines)
var styleToIcon = [String: String]()
var lineNum = 0
for line in myStrings{
//Detecting new style that will be used in placemarks
if line.contains("Style id") && line.contains("normal") && !line.contains("line-"){
let newKey = String(line.split(separator: "\"")[1])
let newValue = String(myStrings[lineNum+4].split(separator: ">")[1].split(separator: "/")[1].split(separator: "<")[0])
styleToIcon[newKey] = newValue
}
//Detecting new placemark on map
else if(line.contains("<Placemark>") && !myStrings[lineNum+2].contains("#line")){
//Get name
var name = myStrings[lineNum+1].split(separator: ">")[1].split(separator: "<")[0]
//Sometimes name has weird CDATA field in it that needs to be removed
if(name.contains("![CDATA")){
name = name.split(separator: "[")[2].split(separator: "]")[0]
}
//Get snippet (description)
var snippet = myStrings[lineNum+2].split(separator: ">")[1].split(separator: "<")[0]
//Sometimes snippet has weird CDATA field in it that needs to be removed
if(snippet.contains("![CDATA")){
snippet = snippet.split(separator: "[")[2].split(separator: "]")[0]
}
//Get style
let style = String(myStrings[lineNum+3].split(separator: ">")[1].split(separator: "#")[0].split(separator: "<")[0] + "-normal")
//Get Coordinates
let coordStringSplit = myStrings[lineNum+6].split(separator: ",")
var lat = 0.0
var long = 0.0
if(coordStringSplit[0].contains("-")){
long = Double(coordStringSplit[0].split(separator: "-")[1])! * -1.0
}else{
long = Double(coordStringSplit[0])!
}
if(coordStringSplit[1].contains("-")){
lat = Double(coordStringSplit[1].split(separator: "-")[1])! * -1.0
}else{
lat = Double(coordStringSplit[1])!
}
//Create marker and add to list of markers
let position = CLLocationCoordinate2D(latitude: lat, longitude: long)
let marker = GMSMarker(position: position)
marker.title = String(name)
marker.snippet = String(snippet)
marker.icon = UIImage(named: styleToIcon[style]!)
markers.append(marker)
}
lineNum += 1
}
}catch{
print(error)
}
}
return markers
}
This is so heavily related to how my kml files look that I doubt it will help anyone else, but I thought I should post it just in case.
Now that we have that method, all we need to do is go back to where we were rendering all of the kml data and render those markers on the map
//Adding markers with icons
let newMarkers = addMarkers(fileName: courseName)
for mark in newMarkers{
mark.map = mapView
}
I also had to go through my kml files manually and fix some of the image names, but that wasn't a big deal. Even if the utility library worked I would need to do that because the utility library only does kml files and not kmz, so each kml file references the same folder for images and uses the same names for images. It's fine, only takes a few minutes per file. Would be nice if there was a kmz library but oh well.
Hopefully this helps someone else, and hopefully I can find the real solution soon (unless its a problem with the utility library in which case hopefully it's fixed soon).
//call method by passing ;
if userLocation.coordinate.latitude != 0.0 && userLocation.coordinate.longitude != 0.0
{
self.updateCurrentPositionMarker(currentLocation: CLLocation(latitude: userLocation.coordinate.latitude, longitude:userLocation.coordinate.longitude))
}
//methods
func updateCurrentPositionMarker(currentLocation: CLLocation) {
self.currentPositionMarker.map = nil
self.currentPositionMarker = GMSMarker(position: currentLocation.coordinate)
if self.imageDataUrl != ""
{
let camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude, zoom: 18.0)
self.mapView.camera = camera
//self.imageDataUrl == image to show
self.currentPositionMarker.iconView = self.drawImageWithProfilePic(urlString:self.imageDataUrl,image: UIImage.init(named: “backgroungImage”)!)
self.currentPositionMarker.zIndex = 1
}
self.currentPositionMarker.map = self.mapView
self.mapView.reloadInputViews()
}
func drawImageWithProfilePic(urlString:String, image: UIImage) -> UIImageView {
let imgView = UIImageView(image: image)
imgView.frame = CGRect(x: 0, y: 0, width: 90, height: 90)
let picImgView = UIImageView()
picImgView.sd_setImage(with:URL(string: urlString))
picImgView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
imgView.addSubview(picImgView)
picImgView.center.x = imgView.center.x
picImgView.center.y = imgView.center.y-10
picImgView.layer.cornerRadius = picImgView.frame.width/2
picImgView.clipsToBounds = true
imgView.setNeedsLayout()
picImgView.setNeedsLayout()
// let newImage = imageWithView(view: imgView)
// return newImage
return imgView
}

Unable to remove previous polyline from last search

I have a slight problem, I am unable to remove the previous polyline created from the previous search.
I have looked at google documentation​ but i am unable to find the right answers.
let routes = json["routes"].arrayValue
for route in routes
{
let routeOverviewPolyline = route["overview_polyline"].dictionary
print("routesOVER:",routeOverviewPolyline)
let points = routeOverviewPolyline?["points"]?.stringValue
let path = GMSPath.init(fromEncodedPath: points!)
let polyline = GMSPolyline(path: path)
if polyline != nil {
print(polyline)
polyline.strokeColor = .black
polyline.strokeWidth = 10.0
polyline.map = self.googleMaps
}
}
}
catch let error as NSError {
print(error)
}
in the google maps, 2 polylines are shown. 1 from the previous search and another from the current search
Google Maps Image
You can clear the mapView before drawing to new polyline on the map.
self.googleMaps.clear()
But above code will clear pins on the map as well. your have to redraw your pins on the map as well

Showing multiple 'GMSMarker' markers on Google maps

I am trying to show multiple location using Google maps, the code showing only one location. I am using for loop. I checked the code using MKMapView and it's working.
Here is the code:
let dict = [self.jsonElement]
for dicts in dict {
let latiCon = (dicts.value(forKey: "lati") as! NSString).doubleValue
let longiCon = (dicts.value(forKey: "longi") as! NSString).doubleValue
// Create a GMSCameraPosition that tells the map to display the
// coordinate -33.86,151.20 at zoom level 6.
let camera = GMSCameraPosition.camera(withLatitude: latiCon, longitude: longiCon, zoom: 6.0)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
self.view = mapView
// Creates a marker in the center of the map.
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: latiCon, longitude: longiCon)
marker.title = "Sydney"
marker.snippet = "Australia"
marker.map = mapView
}
I need to show multiple locations as I said, I have a look to relative answers but I did not find anything match with my question.
this code
let camera = GMSCameraPosition.camera(withLatitude: latiCon, longitude: longiCon, zoom: 6.0)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
self.view = mapView
makeing a new mapView every time in loop so it's natural what you get.
a new mapview + one marker .
move this code outside loop or delete it if you already have a mapview declared before.

Swift Google Maps smoothly rounded polylines

I'm using GoogleMaps for iOS platform, Swift language.
I draw the path according to the Google Maps documentation:
let path = GMSMutablePath()
path.add(previousLocation)
path.add(currentLocation)
let line = GMSPolyline(path: path)
line.strokeWidth = 5
line.strokeColor = .blue
line.map = mapView
My client complains that the route lines intersections must be smoothly rounded. How can I implement this? Some suggestions?
Thanks!
I found the solution.
My problem was that I was always drawing only the last two points:
let path = GMSMutablePath()
path.add(previousLocation)
path.add(currentLocation)
Now, every time when a new location comes, I clear the map and redraw again the entire route:
mapView.clear()
let path = GMSMutablePath()
for location in locationsArray {
path.add(location)
}
let line = GMSPolyline(path: path)
line.strokeWidth = 5
line.strokeColor = .blue
line.map = mapView
Seems that in this way Google Maps draws the route correctly.
Have a look at SwiftSimplify. It is a library that reduces the number of geopoints in the polyline to make it more smooth and efficient.
This library also smooth out the route. I am using this atm. IVBezierPathRenderer