How to pass more information through GMSmarker - swift

How can I pass more data with GMSmarker? For example how can I pass the place_ID? there is only one option for marker1.title. I tried marker2.title but it says marker2 could not be found in GMSmarker().
POIManager.testVariable.forEach {
let marker1 = GMSMarker()
marker1.position = CLLocationCoordinate2D(latitude: $0.geometry.location.lat, longitude: $0.geometry.location.lng)
marker1.title = $0.name
marker2.title = $0.place_id
marker1.map = mapView
locationManager.stopUpdatingLocation()
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
print(marker1.title!)
print(marker2.title!)
return true
}

Related

How to Display User's Place on Snippet Google Maps Swift

I have google map and want to display user's place (like city) in snippet.
How to do that?
here's my current code:
class ViewController: UIViewController, GMSMapViewDelegate, CLLocationManagerDelegate{
#IBOutlet weak var mapView: GMSMapView!
var latitude = -7.034323799999999
var longitude = 110.42400399999997
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
mapView.delegate = self
let camera = GMSCameraPosition.camera(withLatitude: Double(latitude), longitude: Double(longitude), zoom: 17)
mapView.animate(to: camera)
let markerImage = UIImage(named: "ic_home_detail_marker_location")
let markerView = UIImageView(image: markerImage)
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(Double(latitude), Double(longitude))
marker.isDraggable = true
marker.snippet = "\(marker.position)"
mapView.selectedMarker = marker
marker.iconView = markerView
mapView.selectedMarker = marker
marker.map = mapView
}
}
If you want to get the user's city or state name you have to use CLGeocoder.
var currentLatitude:Double!
var currentLongitude:Double!
var cityName:String!
var stateName:String!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locationManager function called")
// Fetch current location coordinates
let locValue:CLLocationCoordinate2D = (locationManager.location?.coordinate)!
currentLatitude = locValue.latitude
currentLongitude = locValue.longitude
print("Current Location = \(currentLatitude!), \(currentLongitude!)")
// Zoom to current location
let camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: currentLatitude!, longitude: currentLongitude!, zoom: 17.0)
viewMap.camera = camera
// check for current city
CLGeocoder().reverseGeocodeLocation(locationManager.location!, completionHandler: {(placemarks, error) -> Void in
if error != nil {
print("Reverse geocoder failed with error" + (error?.localizedDescription)!)
return
}
if (placemarks?.count)! > 0 {
let pm = placemarks?[0]
self.cityName = (pm?.locality)!
self.stateName = (pm?.administrativeArea)
print("Current City: \(self.cityName!)")
print("Curret State: \(self.stateName!)")
}
else {
print("Problem with the data received from geocoder")
}
})
locationManager.stopUpdatingLocation()
}
Now you have the current city stored in a variable.
The next step is that when the user touches a marker, it should display the cityname. For this to achieve implement this:
This delegate must be added:
GMSMapViewDelegate
and this is the marker function, when user taps on it.
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
mapView.delegate = self
marker.snippet = ("Current city: \(cityName!)")
// return false so as to show the marker details or
// return true to hide marker details.
return false
}

Save map annotation using UserDefaults

I have been searching relentlessly for this solution and left with no choice except to rely on the expertise here on Stackoverflow. I am working on saving a map annotation if the app closes and I have been using the UserDefault to save the annotation.
This is the Objective C code that I found and I tried converting it into Swift and I think there is an error with it. I am not too sure. I place this code at viewDidLoad()
This is the save annotation
var pinnedAnnotation: CLLocationCoordinate2D = (parkedCarAnnotation?.coordinate)!
var coordinateData: NSData = NSData(bytesNoCopy: pinnedAnnotation, length: sizeof(pinnedAnnotation), freeWhenDone: false)
UserDefaults.standard.set(coordinateData, forKey: pinnedAnnotation)
UserDefaults.standard.synchronize()
And I needed a load annotation when the app open.
I dont know if viewDidLoad is the right place to put. Previously I put it in a mapView function of updatingLocation
Edited: Added code for further clarification of what I have done that needed to be corrected
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self as MKMapViewDelegate
checkLocationAuthorizationStatus()
tabBar.delegate = self
if UserDefaults.standard.object(forKey: "pinnedAnnotation") != nil {
let annotation = MKPointAnnotation()
self.mapView.addAnnotation(annotation)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let pinnedAnnotation: CLLocationCoordinate2D = (parkedCarAnnotation?.coordinate)!
let locationData = ["latitude": parkedCarAnnotation?.coordinate.latitude, "longitude": parkedCarAnnotation?.coordinate.longitude]
UserDefaults.standard.set(locationData, forKey: "pinnedAnnotation")
UserDefaults.standard.synchronize()
print("Saving data ", UserDefaults.standard.set(locationData, forKey: "pinnedAnnotation"))
}
func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
if(item.tag == 0){
if mapView.annotations.count == 1{
mapView.addAnnotation(parkedCarAnnotation!)
} else {
mapView.removeAnnotation(mapView.annotations as! MKAnnotation)
}
}
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? ParkingSpot{
let identifier = "pin"
var view: MKPinAnnotationView
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.animatesDrop = true
view.pinTintColor = UIColor.orange
view.calloutOffset = CGPoint(x: -8, y: -3)
view.rightCalloutAccessoryView = UIButton.init(type:.detailDisclosure) as UIView
return view
} else {
return nil
}
}
extension ViewController: CLLocationManagerDelegate{
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
centerMapOnLocation(location: CLLocation(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude))
let locationServiceCoordinate = LocationService.instance.locationManager.location!.coordinate
parkedCarAnnotation = ParkingSpot(title: "My Parking Spot", locationName: "Find your way back to your car location", coordinate: CLLocationCoordinate2D(latitude: locationServiceCoordinate.latitude, longitude: locationServiceCoordinate.longitude))
}
}
I'm not entirely sure what you're asking...
For starters when you're saving data to UserDefaults the key needs to be a string, I also believe you'll need to save you data in UserDefaults as a Dictionary
let locationData = ["lat": parkedCarAnnotation?.coordinate?.latitude, "long": parkedCarAnnotation?.coordinate.longitude]
UserDefaults.standard.set(locationData, forKey: "pinned_annotation")
And then to retrieve the data you would call
if let annotationData = UserDefaults.standard.object(forKey: "pinned_annotation") as? Dictionary {
guard let lat = annotationData["lat"], let long = annotationData["long"] else { return }
let coordinate = CLLocationCoordinate2D(latitude: lat, longitude: long)
}
Now you should hopefully be able to set your annotation with the coordinate

Why the MKPolyline didn't show up in my application?

I am trying to create an application, one of its function is to drawing the line while users are moving.
Here is the class
class traceuserViewController: UIViewController,CLLocationManagerDelegate, MKMapViewDelegate {
var locationManager = CLLocationManager()
var startLocation: CLLocation?
var endLocation: CLLocation?
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.locationManager.distanceFilter = 30.0
self.locationManager.startMonitoringSignificantLocationChanges()
self.locationManager.startUpdatingLocation()
mapView.showsUserLocation = true
mapView.mapType = .hybrid
self.mapView.delegate = self
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//user's current location
let nowlocation = locations.last
userLocations.append(nowlocation!)
print("HERE IS THE LOCATION ARRAY")
print(userLocations)
//show the current location region
let center = CLLocationCoordinate2D(latitude: nowlocation!.coordinate.latitude, longitude: nowlocation!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.7, longitudeDelta: 0.7))
self.mapView.setRegion(region, animated: true)
drawRoute(locationArray: userLocations)
}
func drawRoute(locationArray: [CLLocation]) {
if (locationArray.count) > 1 {
var destinationLocIndex = (locationArray.count) - 1
var startLocIndex = (locationArray.count) - 2
let destinationloc = locationArray[destinationLocIndex].coordinate
let startLoc = locationArray[startLocIndex].coordinate
var routeArray = [startLoc, destinationloc]
//test if the function works well or not
print(routeArray)
var geodesicLine = MKGeodesicPolyline(coordinates: routeArray , count: routeArray.count)
mapView.add(geodesicLine, level: .aboveRoads)
}
}
//draw in the mapview
private func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer! {
if overlay is MKPolyline{
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.lineWidth = 5.0
return polylineRenderer
}else{
os_log("Failed to draw the polyline", log: OSLog.default, type: .debug)
return nil
}
}
After many times trying, I still have no idea why it doesn't draw the route on the map when the user is moving, can anyone please I've me some hints?
cheers
I'm inferring that you are using Swift 3 from the code snippet (e.g. the signature of didUpdateLocations; the use of .hybrid rather than Swift 2.3's .Hybrid; etc.).
But, the signature for mapView(_:rendererFor:) is incorrect. In Swift 3, it is:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
...
}
If you ever have a delegate method that doesn't appear to work, add a breakpoint in it and you can confirm if it's called at all or not (and if it is called, you can step through it and diagnose the problem further).

Remove marker on click in swift

i tried to add marker on click and i did it !
but i want to have just 2 marker in google maps.
what should i do ?!
here is my code in swift
mapView.delegate = self
}
func mapView(mapView: GMSMapView, didTapAtCoordinate coordinate: CLLocationCoordinate2D) {
let marker = GMSMarker(position: coordinate)
marker.appearAnimation = kGMSMarkerAnimationPop
marker.title = ""
marker.snippet = ""
marker.map = mapView
}
i want to have a marker for home and a marker for destination
solve with using this function:
var counterMarker: Int = 0
func mapView(mapView: GMSMapView, didTapAtCoordinate coordinate: CLLocationCoordinate2D) {
if counterMarker < 2
{
counterMarker += 1
let marker = GMSMarker(position: coordinate)
marker.appearAnimation = kGMSMarkerAnimationPop
marker.map = mapView
}
}

MKPolyLine not appearing on MapView in Swift

I have the following code in Swift to add an MKPolyline to a MapView. XCode isn't telling me there's an issue, and as far as I've read, this should be working.
Outlet for the MapView:
#IBOutlet weak var mapView: MKMapView!
Variable to hold the coordinates:
var coordinates: [CLLocationCoordinate2D] = []
Get my saved coordinates from Core Data:
var contextMap = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext!
var requestMap = NSFetchRequest(entityName: "Locations")
let predMap = NSPredicate(format: "game = %d", passedGameNumber)
requestMap.predicate = predMap
requestMap.sortDescriptors = [NSSortDescriptor(key:"time", ascending: false)]
self.locationsList = contextMap.executeFetchRequest(requestMap, error: nil)! as [Locations]
Add the coordinates from Core Data to my new array:
for index in 1..<self.locationsList.count{
var lat = Double(self.locationsList[index].latitude)
var long = Double(self.locationsList[index].longitude)
var coordinatesToAppend = CLLocationCoordinate2D(latitude: lat, longitude: long)
coordinates.append(coordinatesToAppend)
}
Create the polyline:
var polyLine = MKPolyline(coordinates: &coordinates, count: coordinates.count)
Add the overlay:
self.mapView.addOverlay(polyLine, level: MKOverlayLevel.AboveRoads)
Add it to the MapView:
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay.isKindOfClass(MKPolyline) {
// draw the track
let polyLine = overlay
let polyLineRenderer = MKPolylineRenderer(overlay: polyLine)
polyLineRenderer.strokeColor = UIColor.blueColor()
polyLineRenderer.lineWidth = 2.0
return polyLineRenderer
}
return nil
}
I simply get a blank MapView. I can print the coordinates array to the console, so I know the data has been added. Any ideas?
The above method will be written like this in Swift3:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay.isKind(of: MKPolyline.self) {
// draw the track
let polyLine = overlay
let polyLineRenderer = MKPolylineRenderer(overlay: polyLine)
polyLineRenderer.strokeColor = UIColor.blue
polyLineRenderer.lineWidth = 2.0
return polyLineRenderer
}
return MKPolylineRenderer()
}
As posted in the comments, the code in the question was fine. I simply wasn't setting the delegate.
mapView.delegate = self