How to deselect a GMSMarker after removing custom infowindow in google maps swift

做~自己de王妃 提交于 2021-01-28 06:20:24

问题


So I have been using Google Maps iOS SDK 4.0.0 and my requirement is like this when I tap on a marker it should add UIViewContoller's view which I easily achieved. Take a look on the following code:

var customeVC:CustomViewController?

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
    
    customeVC = CustomViewController(nibName: "CustomViewController", bundle: nil)
    customeVC?.delegate = self
    self.addChild(customeVC!)
    customeVC?.view.frame = self.view.frame
    self.view.addSubview(customeVC!.view)
    customeVC?.didMove(toParent: self)

    // Remember to return false
    // so marker event is still handled by delegate
    return false
}


func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
    
    //Empty the default infowindow
    return UIView()
}


extension MapViewController: CustomViewControllerDelegate {
    // Triggers when I close the full screen view of CustomViewController
    func didCloseWindow() {
        customeVC?.willMove(toParent: nil)
        customeVC?.removeFromParent()
        customeVC?.view.removeFromSuperview()
        customeVC = nil
    }
}

Now the main the problem is, after closing the window/view if I click on the same marker again (2nd time) its doesn't show the view. But if I click once again (3rd time), it shows.

So I'm suspecting after removing the view the marker doesn't get deselected. But when I tap for the 2nd time its gets deselected and tap for the 3rd time get selected again.

I have textfields & buttons inside CustomViewController thats why I didn't add this view inside the delegate function mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView?. Basically I followed this article which lets you click inside InfoWindow.

I also tried to mapView.selectedMarker = marker inside didTap delegate method and mapView.selectedMarker = nil when removing the view.

How do I deselect the marker so that each time I click on the same marker its should show the view?

Any help will be appreciated. Thanks in advance.


回答1:


After trying for several days finally I solved it. Basically tapping on marker works every time only if you draw only markers. But if you draw markers inside an overlay or a polygon then tapping on same marker for the 2nd time didn't work because 2nd time the following method of GMSMapViewDelegate gets fired.

func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay)

I didn't mention that, I was drawing markers inside an overlay because I never thought it can cause tapping issue. I found someone else also faced the issue earlier but his question was unanswered. So here is what I needed to update inside that delegate method to make it work and the rest code are the same.

I'm setting the isTappable polygon property to false when I'm tapping on a certain polygon and then I can play around with the markers which are drawn inside. Also I'm resetting the isTappable property to true of previously selected polygon as soon as user clicks on other polygon.

class ViewController: GMSMapViewDelegate {
    @IBOutlet weak var mapView:GMSMapView!
    private var selectedPolygon: GMSAptivePolygon?
    
    func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) {
        
        if let polygon = overlay as? GMSPolygon {
            
            // Make sure to restrict markers for a polygon if tapped more than once
            if selectedPolygon != polygon {
                
                // Reset polygon to tappable
                selectedPolygon?.isTappable = true
                
                // Fetch all annotations of this polygon if exits
                fetchMarkers(for: polygon)
                
                polygon.isTappable = false
                selectedPolygon = polygon
            }
        }
    }
}



回答2:


I suspect your problem is more to do with how you are presenting and dismissing your CustomViewController because the didTap delegate method should be called regardless of state.

Initially I would add a test to check if tapping the marker is in-fact triggering the delegate method each time and move some of your presentation code in to a neater method outside of this delegate method e.g.

func showCustomView() {
    // make sure any previous CustomViewController are removed
    if let vc = self.customeVC {
        vc.willMove(toParent: nil)
        vc.removeFromParent()
        vc.view.removeFromSuperview()
        self.customeVC = nil
    }
    // initialise a new CustomViewController
    let cv = CustomViewController(
        nibName: "CustomViewController", 
        bundle: nil
    )
    cv.delegate = self
    self.addChild(cv)
    cv.view.frame = self.view.frame
    self.view.addSubview(cv.view)
    cv.didMove(toParent: self)
    self.customeVC = cv
}

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
    // print to check the marker is being tapped
    print("marker was tapped")
    // run presentation code
    showCustomView()
    // return true to prevent the map from
    // performing its default selection behaviour
    return true
}

I haven't tested this but I hope it helps you clear up the issue, let me know how you get on.


Another thing I would look in to is presenting the CustomViewController modally instead making use of modalPresentationStyle to show the custom view on top of the others without the need to add it as a subview as you are currently.

You'd need something like this in your CustomerViewControllers init

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    self.modalPresentationStyle = .overCurrentContext
    self.modalTransitionStyle = .crossDissolve
    self.modalPresentationCapturesStatusBarAppearance = true
}

Then you'd change your showCustomView() method to something like this

func showCustomView() {
    // make sure any previous CustomViewController are removed
    if let vc = self.customeVC {
        vc.dismiss(animated: true)
        self.customeVC = nil
    }
    // initialise a new CustomViewController
    let cv = CustomViewController(
        nibName: "CustomViewController", 
        bundle: nil
    )
    cv.delegate = self
    self.present(cv, animated: true, completion: nil)
    self.customeVC = cv
}

This would also assume that you have to dismiss the CustomViewController before you can interact with any other part of the map, a screenshot of what you are trying to achieve here might help anyone else to help you.



来源:https://stackoverflow.com/questions/65123628/how-to-deselect-a-gmsmarker-after-removing-custom-infowindow-in-google-maps-swif

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!