iOS SwiftUI:如何检测视图中 UITapGesture 的位置?
iOS SwiftUI: How to detect location of UITapGesture on view?
所以我正在使用 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:
的讨论
Adding your own gesture recognizer to MGLMapView will block the
corresponding gesture recognizer built into MGLMapView. To avoid
conflicts, define which gesture takes precedence.
您可以在您的项目中尝试此代码(几乎只是从上面的链接页面复制而来)编辑:我需要更改原始答案中的行顺序:
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)
}
所以我正在使用 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:
的讨论Adding your own gesture recognizer to MGLMapView will block the corresponding gesture recognizer built into MGLMapView. To avoid conflicts, define which gesture takes precedence.
您可以在您的项目中尝试此代码(几乎只是从上面的链接页面复制而来)编辑:我需要更改原始答案中的行顺序:
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)
}