自定义标记片段未调用按钮操作目标
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 {
函数中。
格伦的回答在某种程度上也是正确的。
我制作了一个自定义视图,当用户点击 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 {
函数中。
格伦的回答在某种程度上也是正确的。