I am using a Swiftui list to show tasks. Each task has a location. When you click on the list row I am using a NavigationLink to navigate to a details page.
I am using a UIViewControllerRepresentable that creates a map view with all the task locations annotated on the map. I had to use UIKit so that you can interact with the annotations. I have set up a delegate that fires when the user clicks the map annotation accessory.
The aim: when the delegate function is called I want to pass back the taskid which is used to navigate to the details page like when the list row is clicked on:
The way I am Navigating from the list:
ForEach(tasksToDisplayInList, id: \.id) { task in
NavigationLink(
destination: TaskDetailsView(taskId: task.id, title: task.title))
{
TaskListRow(task: task)
.padding(.trailing, 5)
.foregroundColor(.textDefault)
}
}
The Task List Map UIViewControllerRepresentable that passes back the pressed task id:
struct TaskListMap: UIViewControllerRepresentable {
typealias UIViewControllerType = TaskListMapController
@Binding var annotations: [TaskAnnotation]
class Coordinator: TaskListMapDelegate {
func didPressMoreDetail(_ mapController: TaskListMapController, for annotation: TaskAnnotation) {
// TaskAnnotation contains the taskId
// Navigate here somehow?
}
var parent: TaskListMap
init(_ parent: TaskListMap) {
self.parent = parent
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> TaskListMapController {
let mapController = TaskListMapController(annotations: annotations)
mapController.delegate = context.coordinator
return mapController
}
func updateUIViewController(_ uiViewController: TaskListMapController, context: Context) {
if annotations.count != uiViewController.mapView.annotations.count {
uiViewController.mapView.removeAnnotations(uiViewController.mapView.annotations)
uiViewController.mapView.addAnnotations(annotations)
}
}
}
As a workaround, this seems to work fine for my purpose: