【问题标题】:Custom marker snippet is not calling the button action target自定义标记片段未调用按钮操作目标
【发布时间】:2017-10-10 09:00:49
【问题描述】:

当用户点击谷歌地图上的标记时,我制作了一个自定义视图。所以我把委托方法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) 的那一行出现错误

致命错误:在展开可选值时意外发现 nil

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    所以基本上点击信息窗口的任何部分只会触发 "didTapWindowOfMarker"

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

    底线是:您需要更改在地图上显示 infoWindow 的方式。您无需在 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
    }
    

    【讨论】:

    • 请查看我更新的问题我开始实施您的答案,但出现错误。
    • 你能清理你的问题并添加你的视图控制器的整个代码吗? :) 那会更好。
    • 这将是很多代码,因为我在这门课上做了很多事情。 emergencyInfo 是一个 UIView 类,我有一个 .xib 在点击标记时显示为 sn-p。这个.xib 有两个按钮。我认为这个错误是因为 UIView 尚未加载或者这就是它说 nil 的原因。
    • 在我的最后一个问题中添加了一个新发现,我发现也请看。
    • 答案很好地组合在一起。 :)
    【解决方案2】:

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

    解决方法可能是使用didTapWindowOfMarker

    您也可以参考this answer

    【讨论】:

    • 我添加了方法didTapWindowOfMarker,是的,如果我点击窗口中的任何位置,它就会起作用。但是,如果我只有一个可能适用的按钮,问题是我有 2 个按钮,并且都有不同的运行方法。
    • 抱歉,但在我看来,这是不可能的,因为我们甚至不知道水龙头的位置。
    • 就我而言,我有两个操作,删除和编辑。我所做的是,我只放置了编辑按钮,然后当用户点击时,我在操作表中显示删除和编辑。
    • 我能想到另一种解决方法。您可以将标记置于中心并通过将其添加到mapview 上方将其显示为覆盖,因此看起来标记具有该弹出窗口。现在您可以随意使用任意数量的按钮。 :)
    • 是的,如果没有其他方法对我有用,那将是最后的选择:) 谢谢你的帮助。
    【解决方案3】:

    所以这就是我做错了。我没有用 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 { 函数内部。

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

    【讨论】:

    • Salam @ChaudhryTalha 我的自定义信息标记中心点位置错误。即当我点击标记时,custominformmarker 不会在标记的顶部中心显示正确的位置。如果您对此有任何想法,请分享。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    相关资源
    最近更新 更多