关于ios:自定义标记代码段未调用按钮操作目标

Custom marker snippet is not calling the button action target

我制作了一个自定义视图,以便用户在Google地图上点击标记时显示。 因此,我将委托方法markerInfoWindow编写为:

1
2
3
4
5
6
7
8
9
10
11
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函数实现为

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

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

更新

基于答案,我开始按照本教程进行操作,因此已实现:

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

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

然后在didTap中,我这样做了:
func mapView(_ mapView:GMSMapView,didTap标记:GMSMarker)-> Bool {

1
2
3
4
5
6
7
8
9
10
11
    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方法更改为:

1
2
3
 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",并且它崩溃时也出现了相同的错误 。


Nikhil是正确的。但是,确实有一个不错的解决方法,需要一些努力和更改。

在继续解决之前,请阅读以下答案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"

然后,针对变通方法(我已经完成了它,并且它已经起作用了),您可以按照本教程http://kevinxh.github.io/swift/custom-and-interactive-googlemaps-ios-sdk-infowindow.html进行操作简单。

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

接下来是在didTap marker中处理您的自定义infoWindow的演示(或显示),在那里您还将处理选择器的设置,例如:

1
2
3
4
5
6
7
8
9
10
11
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
}


GMSMarker被渲染为地图上的图像,因此我们无法获取按钮或任何其他UI元素的回调。

解决方法可能是使用didTapWindowOfMarker

您也可以参考此答案。


所以这就是我做错了。我没有使用xib文件初始化UIView类。所以我补充说:

1
2
3
 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))我添加了:

1
infoWindow = EmergencyViewController.instanceFromNib()

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

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