Reputation: 7987
I've made a custom view to be shown when a user taps on marker on google map. So I've wrote the delegate method markerInfoWindow
as:
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
let infoWindow = Bundle.main.loadNibNamed("emergencyInfo", owner: self.view, options: nil)!.first! as! emergencyInfo
infoWindow.frame = CGRect(x: 0, y: 0, width: 200, height: 110)
infoWindow.titleOfCenter.text = marker.title
infoWindow.addressOfCenter.text = marker.snippet
infoWindow.callNowButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
return infoWindow
}
and buttonTapped
fuction is implemented as
@objc func buttonTapped(sender: UIButton) {
print("Yeah! Button is tapped!")
}
but the problem is that it is not going inside the function.
UPDATE
Based on the answer I started following this tutorial so this is what I've implemented:
First I have declared these two variables:
var tappedMarker = GMSMarker()
var infoWindow = emergencyInfo(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
Then in didTap
I did this:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
let location = CLLocationCoordinate2D(latitude: marker.position.latitude, longitude: marker.position.longitude)
tappedMarker = marker
infoWindow.removeFromSuperview()
infoWindow = emergencyInfo(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
infoWindow.center = mapView.projection.point(for: location)
infoWindow.callNowButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) //getting error on this line
self.view.addSubview(infoWindow)
return false
}
And finally I change the markerInfoWindow
method to:
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
return UIView()
}
Now when I run the code I get error on the line where I'm setting #selector(buttonTapped)
fatal error: unexpectedly found nil while unwrapping an Optional value
Based on some research I found that this error is occuring for the left hand side i.e. infoWindow.callNowButton
because I have a label infoWindow.titleOfCenter.text
for which I've just given "Title"
at the moment and it crashes with the same error on it.
Upvotes: 1
Views: 3107
Reputation: 7987
So this is what I was doing wrong. I was not initializing the UIView Class with xib file. So I added:
class func instanceFromNib() -> emergencyInfo {
return UINib(nibName: "emergencyInfo", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! emergencyInfo
}
and instead of infoWindow = emergencyInfo(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
I added:
infoWindow = EmergencyViewController.instanceFromNib()
inside func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
function.
And Glenn answer was also right up to some extent.
Upvotes: 0
Reputation: 13283
Nikhil is correct. However, indeed there's a sweet workaround for this that requires a little bit of effort and changes.
Before we proceed to the workaround, read this answer https://stackoverflow.com/a/15281141/3231194:
Possibly, as mentioned officially in documentation of Google Maps Android API, the below restriction regarding infowindows applies to Google Maps iOS SDK also :
Info window is not a live View, rather the view is rendered as an image onto the map. As a result, any listeners you set on the view are disregarded and you cannot distinguish between click events on various parts of the view. You are advised not to place interactive components — such as buttons, checkboxes, or text inputs — within your custom info window.
So basically clicking on any part of the infowindow will trigger only "didTapWindowOfMarker"
Then for the workaround (I've done this already and it works), you can just follow this tutorial http://kevinxh.github.io/swift/custom-and-interactive-googlemaps-ios-sdk-infowindow.html which is easy.
Bottomline is: You will need to change how you're showing your infoWindow to the map. Instead of returning your custom infoWindow in markerInfoWindow
, you will replace that with UIView()
.
Next is to handle the presentation (or showing) of your custom infoWindow in didTap marker
, in there you will also handle set the selector, for example:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
guard let tappedJob = marker.userData as? Job else { return false }
self.mapView.selectedMarker = marker
jobInfoWindow?.buttons.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
jobInfoWindow?.job = tappedJob
jobInfoWindow?.center = mapView.projection.point(for: marker.position)
self.view.addSubview(jobInfoWindow!)
return false
}
Upvotes: 4
Reputation: 3868
GMSMarker
gets rendered as images on maps, so we are unable to get callbacks of buttons or any other UI element.
A workaround could be using didTapWindowOfMarker
.
You can also refer to this answer.
Upvotes: 1