I was able to accomplish using the swiftui-introspect library. Essentially falling back to MKMapKit functionality for this particular use case. I am hoping that the new MapReader and MapProxy capability in IOS 17 will help avoid having to use the introspect workaround but I cannot figure out how to use them.
Here is the code that uses introspect to get the coordinates of an annotation as it is being dragged on a map in SwiftUI.
import SwiftUI
import MapKit
import SwiftUIIntrospect
struct ContentView: View {
@State var pinLocation : CLLocationCoordinate2D = .denver
@GestureState var dragAmount = CGSize.zero
@State var mkMapView: MKMapView = .init()
@State var offset: CGSize = .zero
@State private var cameraProsition: MapCameraPosition = .camera(
MapCamera(
centerCoordinate: .denver,
distance: 3729,
heading: 92,
pitch: 70
)
)
func longPressDrag() -> some Gesture {
LongPressGesture(minimumDuration: 0.25)
.sequenced(before: DragGesture(coordinateSpace: .local)
.onEnded { value in
let convertedCoordinate = mkMapView.convert(value.location, toCoordinateFrom: mkMapView)
pinLocation = convertedCoordinate
offset = .zero
print("New Coordinate: \(pinLocation)")
}
.updating($dragAmount) { value, state, transaction in
state = value.translation
offset = value.translation
})
}
var body: some View {
VStack{
Map(
position: $cameraProsition,
interactionModes: []
)
{
Annotation("Center", coordinate: pinLocation) {
RoundedRectangle(cornerRadius: 10)
.foregroundColor(.pink)
.frame(width: 100, height: 100)
.offset(dragAmount)
}
}
.gesture(longPressDrag())
.introspect(.map, on: .iOS(.v17)) { map in
mkMapView = map
}
.mapStyle(.standard(elevation: .automatic))
}
}
}
#Preview {
ContentView()
}