SwiftUI: Как нарисовать линию между двумя координатами при помощи MKOverlayRenderer

Я пытаюсь реализовать в приложении линейку для измерения дальности. То есть нажимая на кнопку линейки я получаю текущие координаты (центр карты) и координаты куда я перемещаю центр карты. В результате я получаю дальность и угол от точки А до точки В.

Мне необходимо нарисовать линию от точки А до точки В.

Пробывал этот пример

но я не понимаю как в массив добавить координаты точки А и точки В чтобы нарисовать линию

@State private var lineCoordinates = [
    // Steve Jobs theatre
    CLLocationCoordinate2D(latitude: 37.330828, longitude: -122.007495),
    // Caffè Macs
    CLLocationCoordinate2D(latitude: 37.336083, longitude: -122.007356),
    // Apple wellness center
    CLLocationCoordinate2D(latitude: 37.336901, longitude:  -122.012345)
  ]

Буду благодарен за подсказку


Ответы (1 шт):

Автор решения: VAndrJ

Вам необходимо добавить UITapGestureRecognizer для MapView, определять координаты нажатия и пробрасывать их для добавления в lineCoordinates.

Результат:

введите сюда описание изображения

По очереди:

  1. Создать наследника MapView и в нём обрабатывать тап:
class TappableMKMapView: MKMapView {
    var onMapTap: ((CLLocationCoordinate2D) -> Void)?
    
    convenience init() {
        self.init(frame: .zero)
        addRecognizer()
    }
    
    private func addRecognizer() {
        let recognizer = UITapGestureRecognizer(target: self, action: #selector(onTap(_:)))
        addGestureRecognizer(recognizer)
    }
    
    @objc private func onTap(_ sender: UITapGestureRecognizer) {
        let location = sender.location(in: self)
        let coordinate = convert(location, toCoordinateFrom: self)
        onMapTap?(coordinate)
    }
}
  1. Заменить в Representable и добавить замыкание:
struct MapView: UIViewRepresentable {
    let region: MKCoordinateRegion
    let lineCoordinates: [CLLocationCoordinate2D]
    let onMapTap: (CLLocationCoordinate2D) -> Void
    
    func makeUIView(context: Context) -> MKMapView {
        let mapView = TappableMKMapView()
        mapView.onMapTap = onMapTap
        mapView.delegate = context.coordinator
        mapView.region = region
        
        let polyline = MKPolyline(coordinates: lineCoordinates, count: lineCoordinates.count)
        mapView.addOverlay(polyline)
        
        return mapView
    }
    
    func updateUIView(_ view: MKMapView, context: Context) {
        let polyline = MKPolyline(coordinates: lineCoordinates, count: lineCoordinates.count)
        view.addOverlay(polyline)
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
}
  1. Использовать:
MapView(
    region: region,
    lineCoordinates: lineCoordinates,
    onMapTap: { coordinate in
        // Прописать как добавлять / удалять
        lineCoordinates.append(coordinate)
    }
)

Gist с полным кодом.

→ Ссылка