2

Here is what I have based on this answer. The code currently allows the user to select a cell but I cannot distinguish which cell is selected or execute any code in response to the selection. In summary, how can I execute code based on the selected cell's name and execute on click. The cell currently highlights in blue where clicked, but I want to identify it and act accordingly based on that selection. Note: I am not looking to select the cell in editing mode. Also, how can I programmatically select a cell without click?

struct OtherView: View {
    @State var list: [String]
    @State var selectKeeper = Set<String>()

    var body: some View {
        NavigationView {
            List(list, id: \.self, selection: $selectKeeper) { item in
                Text(item)
            }
        }
    }
}



Here is a gif demoing the selection

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
Isaac
  • 645
  • 1
  • 7
  • 17

5 Answers5

5

I found a workaround, but the text itself has to be clicked- clicking the cell does nothing:

struct OtherView: View {
    @State var list: [String]
    @State var selectKeeper = Set<String>()

    var body: some View {
        NavigationView {
            List(list, id: \.self, selection: $selectKeeper) { item in
                Text(item)
                  .onTapGesture {
                     print(item)
                  }
            }
        }
    }
}
Isaac
  • 645
  • 1
  • 7
  • 17
0

List selection works in Edit mode, so here is some demo of selection usage

demo

struct OtherView: View {
    @State var list: [String] = ["Phil Swanson", "Karen Gibbons", "Grant Kilman", "Wanda Green"]
    @State var selectKeeper = Set<String>()

    var body: some View {
        NavigationView {
            List(list, id: \.self, selection: $selectKeeper) { item in
                if self.selectKeeper.contains(item) {
                    Text(item).bold()
                } else {
                    Text(item)
                }
            }.navigationBarItems(trailing: HStack {
                if self.selectKeeper.count != 0 {
                    Button("Send") {
                        print("Sending selected... \(self.selectKeeper)")
                    }
                }
                EditButton()
            })
        }
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
0

To spare you the labour pains:

import SwiftUI

struct ContentView: View {
    @State private var selection: String?
    let list: [String] = ["First", "Second", "Third"]
    
    var body: some View {
        NavigationView {
            HStack {
                List(selection: $selection) {
                    ForEach(list, id: \.self) { item in
                        VStack {
                            Text(item)
                        }
                    }
                }
                TextField("Option", text: Binding(self.$selection) ?? .constant(""))
            }
            .frame(minWidth: 100, maxWidth: .infinity, minHeight: 100, maxHeight: .infinity)
        }
    }
}

This solution deals with the problem @Isaac addressed.

screenshot

P. A. Monsaille
  • 152
  • 1
  • 1
  • 10
0

my 2 cents for custom selection and actions works in swift 5.1 / iOS14:

see:

https://gist.github.com/ingconti/49497419e5edd84a5f3be52397c76eb4

I left a lot of debug "print".. to better understand.

ingconti
  • 10,876
  • 3
  • 61
  • 48
0

You can react to the selected item by using onChange on your selection variable.

You can set the selection manually by simply setting the variable. This will also trigger onChange.

Here's some example code that will run directly in Playgrounds:

import SwiftUI
import PlaygroundSupport

struct OtherView: View {
    @State var list: [String] = ["a", "b", "c"]
    @State var selection: String?

    var body: some View {
        NavigationView {
            VStack {
                List(list, id: \.self, selection: $selection) { item in
                    Text(item)
                }
                .onChange(of: selection) {s in
                    // React to changes here
                    print(s)
                }
                
                Button("Select b") {
                    // Example of setting selection programmatically
                    selection = "b"
                }
            }
        }
    }
}

let view = OtherView()
PlaygroundPage.current.setLiveView(view)
Brandon Horst
  • 1,921
  • 16
  • 26