'How does one use NavigationLink isActive binding when working with List in SwiftUI?

The use case is pretty simple. I have a List of places, and each corresponds to a geofence. I need to enable navigation in that particular row(s) whose geofence the user is inside. And the list is dynamic and is fetched from an API. There are similar question on Stackoverflow, but those address only static lists.

I tried using a dictionary of bools, but I am not able to make it work.

This is a simplified mock code:

struct ListView: View {
  @State private var navActive: [UUID: Bool] = [:]
  var body: some View {
    
           List (viewModel.allItems, id: \.id) { item in
           NavigationLink(destination: DetailView(item), isActive: $navActive[item.id]) {
             Text(item.name)
             .onTapGesture {
                if currentLocation.isInside(item.geofence) { navActive[item.id] = true }
             }
         }
      }
   }
}

I get this error: Cannot convert value of type 'Binding<Bool?>' to expected argument type 'Binding<Bool>' on the NavigationLink isActive argument.

Note: I've populated the navActive dictionary with key-value pairs on receiving allItems with an onRecieve modifier



Solution 1:[1]

Here is a possible approach for your use-case

struct ListView: View {
    
    // ... your view model defined here

    @State private var selectedItem: UUID? = nil
    var body: some View {

        List (viewModel.allItems, id: \.id) { item in
            Text(item.name)
                .onTapGesture {
                    self.selectedItem = item.id
                }
                .background(
                    NavigationLink(destination: DetailView(item), tag: item.id,
                        selection: $selectedItem) { EmptyView() }
                        .buttonStyle(PlainButtonStyle())
                )
        }
    }
}

backup

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1