8

I want to set the selected row in a List programmatically.
In my example below via 2 Buttons.

struct ContentView: View {

  @State private var selection = 2

  var body: some View {
    VStack {
      List() {
      //List(selection: $selection)  {.  // does not compile
        Text("Line 0").tag(1)
        Text("Line 1").tag(1)
        Text("Line 2").tag(2)
        Text("Line 3").tag(3)
        Text("Line 4").tag(4)
        Text("Line 5").tag(5)
      }
      .listStyle(SidebarListStyle())
      Text("Selected Item :\(self.selection)")
      HStack {
        Button(action: {if (self.selection < 5 ) { self.selection += 1 }} ) {Text("⬇︎")}
        Button(action: {if (self.selection > 0 ) { self.selection -= 1 }} ) {Text("⬆︎")}
      }
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}

trying to make the List selectable like this:

List(selection: $selection)  

does not compile.
Compiler complains: Unable to infer complex closure return type; add explicit type to disambiguate

2 Answers 2

6

Selection type must be optional. Find below fixed code.

struct TestListSelectionOnAction: View {

  @State private var selection: Int? = 2 // optional !!

  var body: some View {
    VStack {
      List(selection: $selection)  {
        Text("Line 0").tag(0)
        Text("Line 1").tag(1)
        Text("Line 2").tag(2)
        Text("Line 3").tag(3)
        Text("Line 4").tag(4)
        Text("Line 5").tag(5)
      }
      .listStyle(SidebarListStyle())
      Text("Selected Item :\(self.selection ?? -1)")
      HStack {
        Button(action: {
            if (self.selection! < 5 ) { self.selection! += 1 }} ) {Text("⬇︎")}
        Button(action: {
            if (self.selection! > 0 ) { self.selection! -= 1 }} ) {Text("⬆︎")}
      }
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Code compiles now, but the selection in the List is not visible, what's missing?
@mica I tested Asperi answer. It works fine. When launching selection is 2, however not displayed as active row in the List. When removing .listStyle(SidebarListStyle()) it does work though.
is there a way to scroll the newly selected row in the visible area of the List?
0

It won't compile because the tags are not unique. You are setting tag 1 twice. It can not identify the value, thats why List(selection: $selection) does not work either.

 List() {
      //List(selection: $selection)  {.  // should compile now
        Text("Line 0").tag(0)
        Text("Line 1").tag(1)
        Text("Line 2").tag(2)
        Text("Line 3").tag(3)
        Text("Line 4").tag(4)
        Text("Line 5").tag(5)
 }

5 Comments

The Compiler Error remains after the correction with unique tags
@mica Asperi is right, selection has to be declared as optional as stated in doc here developer.apple.com/documentation/swiftui/list
Code compiles with selection as optional, but the selection in the List is not visible, what's missing?
@mica Does Selected Item changes? You mean active item is not selected in the list?
Is there a way to scroll the newly selected row in the visible area of the List?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.