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

时间:2017-10-10 09:00:49

标签: ios swift google-maps swift3 google-maps-markers

当用户点击谷歌地图上的标记时,我已经制作了自定义视图。所以我已将委托方法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) - >布尔{

    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)

的行上出错了
  

致命错误:在解包可选值时意外发现nil

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

3 个答案:

答案 0 :(得分:3)

Nikhil是对的。然而,确实有一个很好的解决方法,需要一点努力和改变。

在我们继续解决之前,请先阅读此答案https://stackoverflow.com/a/15281141/3231194

  

正如Google地图文档中正式提到的那样   Android API,以下关于infowindows的限制适用于   Google Maps iOS SDK也是:

     

信息窗口不是实时视图,而是视图呈现为   图像到地图上。因此,您在视图上设置的任何侦听器都是   被忽视,你无法区分各种点击事件   部分视图。建议您不要放置交互式组件    - 例如按钮,复选框或文本输入 - 在您的自定义中   信息窗口。

     

所以基本上点击infowindow的任何部分都只会触发   “didTapWindowOfMarker”

然后对于解决方法(我已经完成了这项工作),您可以按照本教程http://kevinxh.github.io/swift/custom-and-interactive-googlemaps-ios-sdk-infowindow.html进行操作,这很容易。

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

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

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
}

答案 1 :(得分:1)

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

解决方法可能是使用didTapWindowOfMarker

您也可以参考this answer

答案 2 :(得分:0)

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

 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 {函数内。

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