1

I am using the charts package to display the elevation, when I tap the chart I get the index of the point and I want to use that index to place a marker on the map above it. I.e locations[index].coordinate.

I have the following code and I am trying to pass the index value to my mapView that is also using UIRepresentable to display the map, but I'm having a hard time figuring out how to connect to the publisher.

How do I connect the @Published in the Coordinator class to the MapKitView, so that index will be seen as an Int?

import SwiftUI
import CoreLocation
import Charts

struct ElevationGraphView: UIViewRepresentable  {
    typealias UIViewType = LineChartView
    

    var locations: [CLLocation]?
    let formatter = DateFormatter()
    
    class Coordinator: NSObject, ChartViewDelegate,  ObservableObject {
        
        @Published var index: Int = 0
        
        var parent: ElevationGraphView
        init(_ parent: ElevationGraphView) {
            self.parent = parent
        }
        
        func chartValueSelected(_ uiView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
            
            if let dataSet = uiView.data?.dataSets[highlight.dataSetIndex] {
                let value = dataSet.entryIndex(entry: entry)
                print("Index: \(value)")
                
                // How to get value?
            }
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

struct RaceDetailView: View {
   var body: some View {
        VStack {
            MapKitView(locations: raceDetails.locations, markers: raceDetails.pins, region: raceDetails.region)
            ElevationGraphView(locations: raceDetails.locations)
struct MapKitView: UIViewRepresentable {
    
    let locations: [CLLocation]?
    let markers: [Pin]?
    let region: MKCoordinateRegion?

     ...

    let racePointMarker = RaceMarker(coordinate: locations[index].coordinate, title: "", tint: Color.black)
        mapView.addAnnotation(racePointMarker)
 
4

1 回答 1

1

如我所见,最简单的方法是使用外部可观察对象(以避免将所有这些东西紧密结合在一起)。

这是可能的方法(因此两个视图彼此都不了解)。

class ChartBridge: ObservableObject {
    let shared = ChartBridge()
    @Published var selectedIndex: Int = 0
}

而且您不需要使内部协调器可观察(那是毫无意义的)

class Coordinator: NSObject, ChartViewDelegate {
    
    // ... other code
    
    func chartValueSelected(_ uiView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
        
        if let dataSet = uiView.data?.dataSets[highlight.dataSetIndex] {
            let value = dataSet.entryIndex(entry: entry)
            print("Index: \(value)")
            
            ChartBridge.shared.selectedIndex = value       // << here set !!
        }
    }
}

并在消费者地图视图中观察它

struct MapKitView: UIViewRepresentable {
    @ObservedObject var chart = ChartBridge.shared

    // ... other code

    let racePointMarker = RaceMarker(coordinate: 
        locations[chart.selectedIndex].coordinate,    // << here consume !!
        title: "", tint: Color.black)
        mapView.addAnnotation(racePointMarker)

于 2020-09-24T04:01:00.830 回答