自定义标记片段未调用按钮操作目标

Custom marker snippet is not calling the button action target

我制作了一个自定义视图,当用户点击 google 地图上的标记时会显示该视图。所以我将委托方法 markerInfoWindow 写为:

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
    }

buttonTapped函数实现为

@objc func buttonTapped(sender: UIButton) {
        print("Yeah! Button is tapped!")
    }

但问题是它没有进入函数内部。

更新

根据我开始关注 this tutorial 的答案,这就是我实施的内容:

首先我声明了这两个变量:

var tappedMarker = GMSMarker()
var infoWindow = emergencyInfo(frame: CGRect(x: 0, y: 0, width: 200, height: 100))

然后在 didTap 我这样做了: 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
}

最后我将 markerInfoWindow 方法更改为:

 func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
        return UIView()
}

现在,当我 运行 代码时,我在设置 #selector(buttonTapped)

的那一行出现错误

fatal error: unexpectedly found nil while unwrapping an Optional value

根据一些研究,我发现这个错误发生在左侧,即 infoWindow.callNowButton,因为我有一个标签 infoWindow.titleOfCenter.text,我刚刚在 "Title"那一刻它崩溃了,上面有同样的错误。

GMSMarker 在地图上呈现为图像,因此我们无法获得按钮或任何其他 UI 元素的回调。

解决方法是使用 didTapWindowOfMarker

也可以参考this answer.

尼基尔是正确的。然而,确实有一个很好的解决方法,需要一些努力和改变。

在我们继续解决方法之前,请阅读此答案 :

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"

然后对于解决方法(我已经这样做了并且它有效),您可以按照本教程 http://kevinxh.github.io/swift/custom-and-interactive-googlemaps-ios-sdk-infowindow.html 进行操作,这很简单。

底线是:您需要更改在地图上显示信息窗口的方式。您不会在 markerInfoWindow 中返回您的自定义信息窗口,而是将其替换为 UIView()

下一步是在 didTap marker 中处理自定义信息窗口的显示(或显示),在那里您还将处理设置选择器,例如:

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
}

这就是我做错的地方。我没有用 xib 文件初始化 UIView Class。所以我补充说:

 class func instanceFromNib() -> emergencyInfo {
        return UINib(nibName: "emergencyInfo", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! emergencyInfo
    }

而不是 infoWindow = emergencyInfo(frame: CGRect(x: 0, y: 0, width: 200, height: 100)) 我添加了:

infoWindow = EmergencyViewController.instanceFromNib()

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { 函数中。

格伦的回答在某种程度上也是正确的。