drop a pin when user touch screen in google maps swift - ios

I want to add and remove Marker(pin) in Google Maps.
I want to drop pin with long touch and remove it. I want to use it to select my destination. How can I do it?
let position = CLLocationCoordinate2DMake(10, 10)
let marker = GMSMarker(position: position)
marker.map = mapView

For the ones who're looking for a complete code snippet using Swift:
Implement Protocol GMSMapViewDelegate
Drag an Instance of GMSMapView #IBOutlet weak var googleMapView: GMSMapView!
Mention GMSMapView Delegate within viewDidLoad() as googleMapView.delegate = self
Implement the didTapAt delegate function:
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D){
print("You tapped at \(coordinate.latitude), \(coordinate.longitude)")
googleMapView.clear() // clearing Pin before adding new
let marker = GMSMarker(position: coordinate)
marker.map = googleMapView
}

This code should help you!
//MARK: GMSMapViewDelegate Implimentation.
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
plotMarker(AtCoordinate: coordinate, onMapView: mapView)
}
//MARK: Plot Marker Helper
private func plotMarker(AtCoordinate coordinate : CLLocationCoordinate2D, onMapView vwMap : GMSMapView) {
let marker = GMSMarker(position: coordinate)
marker.map = vwMap
}
PS: Dont forget to confirm to GMSMapViewDelegate in ViewController and assign googleMap.delegate = self somewhere in viewDidLoad()
Hope that helps!

Related

How to set fixed Marker position in Google MapView iOS

Here I'm working on mapKitView using GoogleMapKit and here i want to do when the user drag the marker by using of didBeginDragging, didDragging and didEndDragging
and release the marker at any location point of the screen. I found a helping content to fixed the marker in screen from Hugo Jordao's answer, but this only works to fixed marker position in the center of the screen only.So how can i set marker at any specific screen point??
Dragging Method
func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) {
if marker == mapMarker{
self.markerPosition = GMSCameraPosition(latitude: marker.position.latitude, longitude: marker.position.longitude, zoom: 5.0)
print("End Dragging")
}
}
Set Marker center to the Screen
func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
if self.markerPosition == nil{
mapMarker.position = position.target
}else{
mapMarker.position = self.markerPosition.target
}
}
Answering my own question.
First added variable to store the location value in CGPoint
var markerPosition : CGPoint!
Then convert CLLocationCoordinate2D Location values into the CGPoint and store into markerPosition in didEndDragging marker method.
func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) {
if marker == mapMarker{
self.markerPosition = self.mapView.projection.point(for: CLLocationCoordinate2D(latitude: marker.position.latitude, longitude: marker.position.longitude))
print("End Dragging")
}
}
After that set GMSMarker position at any screen point as per CGPoint values into the MAPView
func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
if self.markerPosition == nil{
//To set pin into the center of mapview
mapMarker.position = position.target
}else{
//To set pin into the any particular point of the screen on mapview
let coordinate = self.mapView.projection.coordinate(for: self.markerPosition)
mapMarker.position = coordinate
}
}

how can I multiple tapping with single marker

by tapping, it makes marker infinity. i want to one marker where I tapped. over and over again. not with lots markers.
I used MapView.clean(). but it delete every markers.
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D)
{
let marker = GMSMarker(position: coordinate)
marker.position.latitude = coordinate.latitude
marker.position.longitude = coordinate.longitude
print("hello")
print(markerr.position.latitude)
let ULlocation = markerr.position.latitude
let ULlgocation = markerr.position.longitude
print(ULlocation)
print(ULlgocation)
marker.map = self.mapView
}
Create the marker outside the didTapAt coordinate method and change it's coordinates in this method
class ViewController: UIViewController, GMSMapViewDelegate {
let marker = GMSMarker()
override func viewDidLoad() {
super.viewDidLoad()
marker.map = self.mapView
}
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D)
{
marker.position = coordinate
}
}

swift google maps will not show snippet window

for some odd reason when a marker is tapped google map will not show the snippet window in my swift code. I just dont see what im doing wrong. I get the marker on the map but when i tap it it does not show anything. Thank you in advance.
func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
let position = place.coordinate
self.dismiss(animated: true) {
let marker = GMSMarker(position: position)
marker.title = "title here"
marker.snippet = "my snippet here"
marker.map = self.mapView
}
}
I had to remove the delegate below in order for the infowindow to show.
// func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
// print("marker Tapped")
//
// return true
// }
You can put in the delegate
mapView.selectedMarker = marker
so the code will be as this :
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
print("marker Tapped")
mapView.selectedMarker = marker
return true
}
Hope this will help you.

How do you set the delegate when passing data from ViewController to View?

Here's the relevant code:
in ViewController
protocol LocationDelegate {
func setLocation(coordinate: CLLocationCoordinate2D)
}
var locationDelegate: LocationDelegate?
func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) {
locationDelegate?.setLocation(coordinate: coordinate)
createPostView = createViewFromNib()
createPostView.center = SCREEN_CENTER_POSITION
self.view.addSubview(createPostView)
}
in CreatePostView
class CreatePostView: UIView, UINavigationControllerDelegate, LocationDelegate {
var location: CLLocation! = CLLocation()
func setLocation(coordinate: CLLocationCoordinate2D) {
self.location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
}
}
This doesn't work. "location" is always being saved as empty and I believe it's because I haven't set the delegate. I know this is usually done in prepareForSegue when passing data between two ViewControllers, but in this case, I'm not sure when to set it. How should I go about this?
I think you are confused about how the delegate pattern works.
If I understand what you are trying to do... In ViewController you are accepting a longPress on the mapView, which is also passing the CLLocationCoordinate2D. You then create a CreatePostView which you want to add to your view as a subview... and you want to set the location var in that createPostView instance to the long-press coordinate. Correct?
If so, you don't need the delegate at all.
Instead, your CreatePostView class should have:
class CreatePostView: UIView, UINavigationControllerDelegate {
var location: CLLocation! = CLLocation()
func setLocation(coordinate: CLLocationCoordinate2D) {
self.location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
}
}
and your ViewController class should have:
func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) {
// instantiate your CreatePostView
createPostView = createViewFromNib()
// set it's .center property
createPostView.center = SCREEN_CENTER_POSITION
// here is where you "pass in" the coordinate
createPostView.setLocation(coordinate: coordinate)
// add it to your view
self.view.addSubview(createPostView)
}
You would want to use a delegate pattern if, for example, your createPostView had text fields and buttons, and you want to pass those values "up" to your ViewController.
func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) {
createPostView = createViewFromNib() as! CreatePostView
createPostView.setLocation(coordinate: coordinate)
createPostView.center = SCREEN_CENTER_POSITION
self.view.addSubview(createPostView)
}

How to change google maps marker color when selected in swift?

I have a view controller with a GMSMapView and have loaded a number of markers onto the map. I can change which marker is selected with mapView.selectedMarker = ... but how do I change the color of the selected marker?
You can use GMSMarker.markerImage(with: <UIColor?>) to reset a marker's icon.
Docs: Google Maps iOS SDK GMSMarker Class Reference
import GoogleMaps
// view controller
class MapViewController: UIViewController {
// outlets
#IBOutlet weak var mapView: GMSMapView!
// view did load method
override func viewDidLoad() {
super.viewDidLoad()
// set map view delegate
mapView.delegate = self
}
}
// extension for GMSMapViewDelegate
extension MapViewController: GMSMapViewDelegate {
// tap map marker
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
print("didTap marker \(marker.title)")
// remove color from currently selected marker
if let selectedMarker = mapView.selectedMarker {
selectedMarker.icon = GMSMarker.markerImage(with: nil)
}
// select new marker and make green
mapView.selectedMarker = marker
marker.icon = GMSMarker.markerImage(with: UIColor.green)
// tap event handled by delegate
return true
}
}
Simple Way Swift 5
marker.icon = GMSMarker.markerImage(with: UIColor.green)
The accepted answer wasn't working for me because if a user tapped a non-marker on the map, selectedMarker would be set to nil. If the user then tapped another marker, triggering the didTap callback, the selectedMarker would be nil and thus retain its selected state/color.
The fix for me was to remove that selectedMarker logic from didTap and move it to didCloseWindowOf.
Here's the code:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
marker.icon = UIImage(named: "map_marker_selected")
return false // return false to display info window
}
func mapView(_ mapView: GMSMapView, didCloseInfoWindowOf marker: GMSMarker) {
marker.icon = UIImage(named: "map_marker_unselected")
}
This works because when the user taps a non-marker, the info window closes which triggers didCloseInfoWindowOf.
If you use RxSwift, here is an elegant solution with RxGoogleMaps
Observable.combineLatest(mapView.rx.selectedMarker,
mapView.rx.selectedMarker.skip(1))
.subscribe(onNext: { (old, new) in
old?.icon = GMSMarker.markerImage(with: nil)
new?.icon = GMSMarker.markerImage(with: UIColor.red)
})
.disposed(by: disposeBag)

Resources