SwiftUI/MapKit注释选择和导航 [英] SwiftUI / MapKit Annotation Selection and Navigation

查看:86
本文介绍了SwiftUI/MapKit注释选择和导航的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前有一个SwiftUI视图,该视图显示一个充满针脚的地图.该地图有一个委托,可以确定何时选择了引脚,并获取与该引脚关联的自定义对象.

I currently have a SwiftUI view that displays a map full of pins. The map has a delegate which can determine when a pin is selected and get the custom object associated with that pin.

问题在于,一旦委托人确定选择了引脚,我就需要我的SwiftUI视图使用委托人检索到的自定义对象导航/推送到详细信息页面.

The problem is that once the delegate determines that the pin has been selected, I need my SwiftUI view to navigate/push to a detail page with the custom object that the delegate retrieved.

我能想到的最好的比较是尝试将选定的注释视为主视图的导航链接按钮.

The best comparison I can think of is trying to treat the selected annotation as a navigation link button for the main view.

如何从地图委托人传递到SwiftUI视图?

How do I communicate from the map delegate to the SwiftUI view?


import SwiftUI
import MapKit

/// The SwiftUI view I am referring to
struct ContentView: View {
    var body: some View {
        ZStack {
            MapView()
        }
        .edgesIgnoringSafeArea(.all)
    }
}


/// The custom object I am referring to
class LandmarkAnnotation: NSObject, MKAnnotation {
    let title: String?
    let subtitle: String?
    let coordinate: CLLocationCoordinate2D
    init(title: String?,
         subtitle: String?,
         coordinate: CLLocationCoordinate2D) {
        self.title = title
        self.subtitle = subtitle
        self.coordinate = coordinate
    }
}

/// The delegate I am referring to
class MapViewCoordinator: NSObject, MKMapViewDelegate {
    var mapViewController: MapView
    
    init(_ control: MapView) {
        self.mapViewController = control
    }
    
    func mapView(_ mapView: MKMapView, viewFor
                    annotation: MKAnnotation) -> MKAnnotationView?{
        ...
        return annotationView
    }
    
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        let circle = MKCircleRenderer(overlay: overlay)
        ...
        return circle
    }
    
    /// This is where the delegate gets the object for the selected annotation
    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        if let v = view.annotation as? LandmarkAnnotation {
            print(v.coordinate)
        }
    }
}


struct MapView: UIViewRepresentable {
    
    var markers: [CLLocationCoordinate2D] = [CLLocationCoordinate2D(
                                                latitude: 34.055404, longitude: -118.249278),CLLocationCoordinate2D(
                                                    latitude: 34.054097, longitude: -118.249664), CLLocationCoordinate2D(latitude: 34.053786, longitude: -118.247636)]
    var convertedMarkers: [LandmarkAnnotation] = []
    
    init() {
        convertedMarkers = cordToMark(locations: self.markers)
    }
    
    func makeUIView(context: Context) -> MKMapView{
        MKMapView(frame: .zero)
    }
    
    func cordToMark(locations: [CLLocationCoordinate2D]) -> [LandmarkAnnotation] {
        var marks: [LandmarkAnnotation] = []
        for cord in locations {
            let mark = LandmarkAnnotation(title: "Test", subtitle: "Sub", coordinate: cord)
            marks.append(mark)
        }
        return marks
    }
    
    func makeCoordinator() -> MapViewCoordinator{
        MapViewCoordinator(self)
    }
    
    func updateUIView(_ view: MKMapView, context: Context){
        let coordinate = CLLocationCoordinate2D(
            latitude: 34.0537767, longitude: -118.248)
        let mapCamera = MKMapCamera()
        mapCamera.centerCoordinate = coordinate
        mapCamera.pitch = 10
        mapCamera.altitude = 3000
        view.camera = mapCamera
        view.mapType = .mutedStandard
        view.delegate = context.coordinator
        view.addAnnotations(self.convertedMarkers)
        let radiusCircle = MKCircle(center: CLLocationCoordinate2D(
                                        latitude: 34.0537767, longitude: -118.248), radius: 300 as CLLocationDistance)
        view.addOverlay(radiusCircle)
        let locationCircle = MKCircle(center: CLLocationCoordinate2D(
                                        latitude: 34.0537767, longitude: -118.248), radius: 3 as CLLocationDistance)
        view.addOverlay(locationCircle)
    }
    
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environment(\.colorScheme, .light)
    }
}


这是模拟器中显示的地图图像

Here is an image of the map that is displayed in the simulator

推荐答案

这里是个主意(草稿)

  1. 向可表示形式添加回调

struct MapView: UIViewRepresentable {
    var didSelect: (LandmarkAnnotation) -> ()  // callback

  1. ContentView

ZStack {
    MapView() { annotation in
       // store/pass annotation somewhere, and
       // activate navigation link here, eg. via isActive or selection
    }
}

  1. 激活委托中的回调

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    if let v = view.annotation as? LandmarkAnnotation {
        print(v.coordinate)

       self.mapViewController.didSelect(v)    // << here !!
    }
}

这篇关于SwiftUI/MapKit注释选择和导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆