I have an understanding problem migrating to the new iOS17 MapKit in SwiftUI. I have this code in my app:

NavigationStack {
    Map(coordinateRegion: $mapRegion, annotationItems: destinations) { destination in
        MapAnnotation(coordinate: destination.coordinate) {
            NavigationLink {
                DestinationDetailView(destination: destination)
            } label: {
                VStack {
                    Image(systemName: "\(destination.locationType.attributes.icon)")
                        .font(.largeTitle)
                        .foregroundColor(destination.locationType.attributes.color)
                    Text("\(destination.name)")
                        .foregroundColor(.black)
                        .font(.subheadline)
                }
            }
        }
    }
}

Works fine, opens the DestinationDetailView when an annotation is selected. But has warning (due to new iOS 17): 'MapAnnotation' was deprecated in iOS 17.0: Use Annotation along with Map initializers that take a MapContentBuilder instead.

I read the new MapKit specification and changed the code to:

NavigationStack {
    Map(position: $position, selection: $mapSelection) {
        
        ForEach(destinations, id: \.locationId) { destination in
            Marker(destination.name, coordinate: destination.coordinate)
                .tint(destination.locationType.attributes.color)
                .tag(destination)
        }
    }
    .onChange(of: mapSelection) { oldValue, newValue in
        if mapSelection != nil {
            print("Selection: \(mapSelection!.name)")
            NavigationLink("",destination: DestinationDetailView(destination: mapSelection!))
        }
    }
}
  

It displays the same map, animates the marker when selected, but does not launch the navigation towards the DestinationDetailView. What am I missing?

1

There are 1 best solutions below

2
On BEST ANSWER

You can use navigationDestination(item:destination:). Pass the same binding you used for map selection into this, and give a closure that returns the destination view, given a selected item.

.navigationDestination(item: $mapSelection) { selection in
    DestinationDetailView(destination: selection)
}