问题描述
所以我使用的是 MapBox。地图结构符合 UIViewRepresentable 协议。在我的 makeUIView() 函数中,我创建了一个点击手势识别器并将其添加到地图视图中。
struct Map: UIViewRepresentable {
private let mapView: MGLMapView = MGLMapView(frame: .zero,styleURL: MGLStyle.streetsstyleURL)
func makeUIView(context: UIViewRepresentableContext<Map>) -> MGLMapView {
mapView.delegate = context.coordinator
let gestureRecognizer = UITapGestureRecognizer(target: context.coordinator,action: Selector("tappedMap"))
mapView.addGestureRecognizer(gestureRecognizer)
return mapView
}
func updateUIView(_ uiView: MGLMapView,context: UIViewRepresentableContext<Map>) {
print("Just updated the mapView")
}
func makeCoordinator() -> Map.Coordinator {
Coordinator(appState: appState,self)
}
// other functions that make the struct have functions required by MapBox
func makeCoordinator() -> Map.Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject,MGLMapViewDelegate {
var control: Map
//a bunch of delegate functions
@objc func tappedMap(sender: UITapGestureRecognizer) {
let locationInMap = sender.location(in: control)
let coordinateSet = sender.convert(locationInMap,toCoordinateFrom: control)
}
}
}
tappedMap 函数中的任何一行都无法正确编译...此外,当我在 tappedMap 的参数中有“sender: UITapGestureRecognizer”时,我会在点击 mapView 时导致应用程序崩溃——如果我删除了参数,那么该函数至少被正确调用而不会崩溃。请帮忙
解决方法
好的,第一个问题是您在 tapGesture 声明中的选择器定义。改成这样:
let gestureRecognizer = UITapGestureRecognizer(target: context.coordinator,action: #selector(Coordinator.tappedMap(sender:)))
此外,您需要管理手势识别器的优先级,因为 MGLMapView 内部包含 UIGestureRecognizer 逻辑。我发现了一个关于 here 的讨论:
将您自己的手势识别器添加到 MGLMapView 将阻止 MGLMapView 中内置了相应的手势识别器。避免 冲突,定义哪个手势优先。
您可以在您的项目中尝试此代码(几乎只是从上面的链接页面复制)编辑:我需要更改原始答案中的行顺序:
let gestureRecognizer = UITapGestureRecognizer(target: context.coordinator,action: Selector("tappedMap"))
// HERE'S THE NEW STUFF:
for recognizer in mapView.gestureRecognizers! where recognizer is UITapGestureRecognizer {
gestureRecognizer.require(toFail: recognizer)
}
mapView.addGestureRecognizer(gestureRecognizer)
编辑:我能够对此进行测试。
我对您的 tappedMap
选择器内部的逻辑有些困惑:也许您的意思是这样的?
@objc func tappedMap(sender: UITapGestureRecognizer) {
let locationInMap = sender.location(in: control.mapView)
let coordinateSet = sender.view?.convert(locationInMap,to: control.mapView)
}