skip to Main Content

So I have this minimum repro code:

struct ListViewWithNewAPI: View {
  @State var selectedString: String? = nil
  
  var body: some View {
    let details = ["foo", "bar", "baz"]
    
    NavigationStack {
      List {
        ForEach(details, id: .self) { detail in
          NavigationLink(detail, value: detail)
        }
      }
      .navigationDestination(item: $selectedString) { detail in
        Text("This is a detailed page for (detail)")
          .navigationTitle("Detail page")
      }
      .navigationTitle("List page")
    }
  }
}

When I tap on the link, I got a warning:

A NavigationLink is presenting a value of type “String” but there is no matching navigationDestination declaration visible from the location of the link. The link cannot be activated.

But as you can tell, I did provide the navigationDestination with correct String type. What is going on here?

Edit: This is my old way of writing it:

    List {
      ForEach(details, id: .self) { detail in
        let destination = Text("This is a detailed page for (detail)")
          .navigationTitle("Detail page")
        
        NavigationLink(
          detail,
          destination: destination,
          tag: detail,
          selection: $selectedString)
      }
    }

This API has been deprecated, but it was working well – I did not have to manually set $selectedString.

2

Answers


  1. You are really close here. The navigationDestination you should be using is the for variation that allows you to associate it with a type instead of a selected value:

    .navigationDestination(for: String.self, destination: { detail in
        Text("This is a detailed page for (detail)")
            .navigationTitle("Detail page")
    })
    
    Login or Signup to reply.
  2. I think you are mixing the different ways of using .navigationDestination.

    You can either do it like this:

    .navigationDestination(for: String.self) { detail in
        Text("This is a detailed page for (detail)")
            .navigationTitle("Detail page")
    }
    

    or… you can leave the .navigationDestination like you have it and change the links to something that updates the state variable selectedString, like this:

    ForEach(details, id: .self) { detail in
        Button(detail) { selectedString = detail }
    }
    

    EDIT This works too and gives you the right arrow like before. It’s a slightly different way of building the List:

    NavigationStack {
        List(details, id: .self, selection: $selectedString) { detail in
            NavigationLink(detail, value: detail)
        }
        .navigationDestination(item: $selectedString) { detail in
            Text("This is a detailed page for (detail)")
                .navigationTitle("Detail page")
        }
        .navigationTitle("List page")
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search