The way to achieve this is track the selected item:
@State private var results: [SearchResult] = []
@State private var selectedResult: UUID?
Your items should already be Identifiable, something like this:
struct SearchResult: Identifiable {
let id = UUID()
let mapItem: MKMapItem
}
Then when you iterate through your map annotations you can decide to generate the selected one, or non-selected one:
Map(coordinateRegion: $region, interactionModes: .all, showsUserLocation: true, userTrackingMode: $trackUser, annotationItems: results) { result in
buildAnnotation(result, isSelected: result.id == selectedResult)
}
And when building the annotation, add a tap gesture recognizer to change the selected item, and center the map if desired:
private func buildAnnotation(_ result: SearchResult, isSelected: Bool) -> some MapAnnotationProtocol {
MapAnnotation(coordinate: result.mapItem.placemark.coordinate, anchorPoint: CGPoint(x: 0.5, y: 1.0)) {
MyCustomView(isSelected: isSelected)
.onTapGesture {
withAnimation {
selectedResult = result.id
region.center = result.mapItem.placemark.coordinate
}
}
}
}
The MyCustomView is just a normal SwiftUI View with body and you can pass in whatever parameters you want to use from the item it represents, including whether it's selected or not.