无法将点击手势识别器添加到 SwiftUI MKMapView UIViewRepresentable
Can't add Tap Gesture Recognizer to SwiftUI MKMapView UIViewRepresentable
我有一个带有 SwiftUI 生命周期的 SwiftUI 应用程序,我正在尝试使用点击手势来
在 MKMapView 中工作。我似乎无法正确获取对地图的引用。我都
想要在本小节中做的是点击地图并添加注释。那时我会
也使用注释的坐标。
这是代码。
struct MapView: UIViewRepresentable {
typealias UIViewType = MKMapView
@State private var myMapView: MKMapView?
class Coordinator: NSObject, MKMapViewDelegate {
var control: MapView
let parent = MapView()
let sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
init(_ control: MapView) {
self.control = control
}
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
if let annotationView = views.first {
if let annotation = annotationView.annotation {
if annotation is MKUserLocation {
let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 2000, longitudinalMeters: 2000)
mapView.setRegion(region, animated: true)
}
}
}
}//did add
@objc func addAnnotationOnTapGesture(sender: UITapGestureRecognizer) {
if sender.state == .ended {
print("in addAnnotationOnTapGesture")
let point = sender.location(in: parent.myMapView)
print("point is \(point)")
let coordinate = parent.myMapView?.convert(point, toCoordinateFrom: parent.myMapView)
print("coordinate?.latitude is \(String(describing: coordinate?.latitude))")
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate ?? sfCoord
annotation.title = "Start"
parent.myMapView?.addAnnotation(annotation)
}
}
}//coord
func makeUIView(context: Context) -> MKMapView {
let map = MKMapView()
map.showsUserLocation = true
map.delegate = context.coordinator
DispatchQueue.main.async {
self.myMapView = map
}
let gRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.addAnnotationOnTapGesture(sender:)))
map.addGestureRecognizer(gRecognizer)
return map
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func updateUIView(_ uiView: MKMapView, context: Context) {
}
}//struct MapView
和 LocationManager 供参考:
class LocationManager: NSObject, ObservableObject {
private let locationManager = CLLocationManager()
@Published var location: CLLocation? = nil
override init() {
super.init()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.distanceFilter = kCLDistanceFilterNone
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print(status)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
self.location = location
}
}//extension
最后是 ContentView:
struct ContentView: View {
@ObservedObject var locationManager = LocationManager()
var body: some View {
MapView()
}
}
点击地图会显示如下控制台输出:
在添加AnnotationOnTapGesture
点是 (156.0, 515.6666564941406)
坐标?.纬度为零
如有任何指导,我们将不胜感激。 Xcode 12.5 iOS 14.5
在您的 Coordinator
中,您有两个对 MapView
的引用。一个 (control
) 在 init
中设置,代表您想要的实际视图。另一个 (parent
) 在您的 Coordinator
中定义,实际上并不是视图层次结构的一部分。因此,当您尝试从中获取坐标时,它会 returns nil
。您可以将所有引用更改为 control
并且它有效:
class Coordinator: NSObject, MKMapViewDelegate {
var control: MapView
let sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
init(_ control: MapView) {
self.control = control
}
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
if let annotationView = views.first {
if let annotation = annotationView.annotation {
if annotation is MKUserLocation {
let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 2000, longitudinalMeters: 2000)
mapView.setRegion(region, animated: true)
}
}
}
}//did add
@objc func addAnnotationOnTapGesture(sender: UITapGestureRecognizer) {
if sender.state == .ended {
print("in addAnnotationOnTapGesture")
let point = sender.location(in: control.myMapView)
print("point is \(point)")
let coordinate = control.myMapView?.convert(point, toCoordinateFrom: control.myMapView)
print("coordinate?.latitude is \(String(describing: coordinate?.latitude))")
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate ?? sfCoord
annotation.title = "Start"
control.myMapView?.addAnnotation(annotation)
}
}
}//coord
我有一个带有 SwiftUI 生命周期的 SwiftUI 应用程序,我正在尝试使用点击手势来 在 MKMapView 中工作。我似乎无法正确获取对地图的引用。我都 想要在本小节中做的是点击地图并添加注释。那时我会 也使用注释的坐标。
这是代码。
struct MapView: UIViewRepresentable {
typealias UIViewType = MKMapView
@State private var myMapView: MKMapView?
class Coordinator: NSObject, MKMapViewDelegate {
var control: MapView
let parent = MapView()
let sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
init(_ control: MapView) {
self.control = control
}
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
if let annotationView = views.first {
if let annotation = annotationView.annotation {
if annotation is MKUserLocation {
let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 2000, longitudinalMeters: 2000)
mapView.setRegion(region, animated: true)
}
}
}
}//did add
@objc func addAnnotationOnTapGesture(sender: UITapGestureRecognizer) {
if sender.state == .ended {
print("in addAnnotationOnTapGesture")
let point = sender.location(in: parent.myMapView)
print("point is \(point)")
let coordinate = parent.myMapView?.convert(point, toCoordinateFrom: parent.myMapView)
print("coordinate?.latitude is \(String(describing: coordinate?.latitude))")
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate ?? sfCoord
annotation.title = "Start"
parent.myMapView?.addAnnotation(annotation)
}
}
}//coord
func makeUIView(context: Context) -> MKMapView {
let map = MKMapView()
map.showsUserLocation = true
map.delegate = context.coordinator
DispatchQueue.main.async {
self.myMapView = map
}
let gRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.addAnnotationOnTapGesture(sender:)))
map.addGestureRecognizer(gRecognizer)
return map
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func updateUIView(_ uiView: MKMapView, context: Context) {
}
}//struct MapView
和 LocationManager 供参考:
class LocationManager: NSObject, ObservableObject {
private let locationManager = CLLocationManager()
@Published var location: CLLocation? = nil
override init() {
super.init()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.distanceFilter = kCLDistanceFilterNone
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print(status)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
self.location = location
}
}//extension
最后是 ContentView:
struct ContentView: View {
@ObservedObject var locationManager = LocationManager()
var body: some View {
MapView()
}
}
点击地图会显示如下控制台输出:
在添加AnnotationOnTapGesture
点是 (156.0, 515.6666564941406)
坐标?.纬度为零
如有任何指导,我们将不胜感激。 Xcode 12.5 iOS 14.5
在您的 Coordinator
中,您有两个对 MapView
的引用。一个 (control
) 在 init
中设置,代表您想要的实际视图。另一个 (parent
) 在您的 Coordinator
中定义,实际上并不是视图层次结构的一部分。因此,当您尝试从中获取坐标时,它会 returns nil
。您可以将所有引用更改为 control
并且它有效:
class Coordinator: NSObject, MKMapViewDelegate {
var control: MapView
let sfCoord = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194)
init(_ control: MapView) {
self.control = control
}
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
if let annotationView = views.first {
if let annotation = annotationView.annotation {
if annotation is MKUserLocation {
let region = MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 2000, longitudinalMeters: 2000)
mapView.setRegion(region, animated: true)
}
}
}
}//did add
@objc func addAnnotationOnTapGesture(sender: UITapGestureRecognizer) {
if sender.state == .ended {
print("in addAnnotationOnTapGesture")
let point = sender.location(in: control.myMapView)
print("point is \(point)")
let coordinate = control.myMapView?.convert(point, toCoordinateFrom: control.myMapView)
print("coordinate?.latitude is \(String(describing: coordinate?.latitude))")
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate ?? sfCoord
annotation.title = "Start"
control.myMapView?.addAnnotation(annotation)
}
}
}//coord