在 google 地图 swift 中删除自定义信息窗口后如何取消选择 GMSMarker

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

所以我一直在使用 Google Maps iOS SDK 4.0.0,我的要求是这样的,当我点击一个标记时,它应该添加我很容易实现的 UIViewContoller 视图。看看下面的代码:

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
    }
}

现在的主要问题是,在关闭 window/view 之后,如果我再次(第二次)单击同一个标记,它不会显示视图。但是,如果我再次单击(第 3 次),它会显示。

所以我怀疑在删除视图后标记没有被取消选择。但是当我第二次点击时它被取消选择并再次点击第三次被选中。

我在 CustomViewController 中有文本字段和按钮,这就是为什么我没有在委托函数中添加此视图的原因 mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView?。基本上我遵循了这个 article,它可以让你在 InfoWindow 中点击。

我还尝试在 didTap 委托方法中 mapView.selectedMarker = marker 并在删除视图时 mapView.selectedMarker = nil

如何取消选择标记,以便每次单击同一个标记时它都应该显示视图?

如有任何帮助,我们将不胜感激。提前致谢。

我怀疑你的问题更多地与你如何呈现和解散你的 CustomViewController 有关,因为无论状态如何,都应调用 didTap 委托方法。

最初我会添加一个测试来检查点击标记是否实际上每次都触发了委托方法,并将您的一些演示代码移到该委托方法之外的更整洁的方法中,例如

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
}

我还没有测试过这个,但我希望它能帮助你解决问题,让我知道你的进展情况。


我要考虑的另一件事是模态呈现 CustomViewController 而不是使用 modalPresentationStyle 在其他视图之上显示自定义视图,而无需将其添加为子视图你目前是。

您的 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
}

然后您将 showCustomView() 方法更改为类似这样的方法

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
}

这还假定您必须先关闭 CustomViewController 才能与地图的任何其他部分进行交互,您在这里尝试实现的屏幕截图可能会帮助其他人帮助您。

试了几天终于解决了。基本上,只有当您只绘制标记时,每次点击标记才有效。但是,如果您在叠加层或多边形内绘制标记,则第二次点击同一标记不起作用,因为第二次 GMSMapViewDelegate 的以下方法被触发。

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

我没有提到这一点,我在叠加层内绘制标记,因为我从没想过它会导致点击问题。我发现其他人之前也遇到了 issue 但他的问题没有得到解答。所以这是我需要在该委托方法内部更新以使其工作的内容,其余代码相同。

当我点击某个多边形时,我将 isTappable 多边形 属性 设置为 false,然后我可以玩弄绘制在里面的标记。 此外,只要用户单击其他多边形,我就会将先前选择的多边形的 isTappable 属性 重置为 true

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
            }
        }
    }
}