iOS SwiftUI:如何在视图中检测 UITapGesture 的位置?

问题描述

所以我使用的是 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)
}