Search code examples
xcodemacosswiftuixcode13

SwiftUI 3 MacOs Table single selection and double click open sheet


import SwiftUI

struct ContentView: View {
    
    @State private var items: [ItemModel] = Array(0...100).map { ItemModel(id: $0, title: "item \($0)", age: $0) }
    @State private var selection = Set<ItemModel.ID>()
    @State private var sorting = [KeyPathComparator(\ItemModel.age)]
    
    var body: some View {
        Table(items, selection: $selection, sortOrder: $sorting) {
            TableColumn("id", value: \.id) { Text("\($0.id)") }
            TableColumn("title", value: \.title)
            TableColumn("age", value: \.age) { Text("\($0.age)") }
        }
        .onChange(of: sorting) {
            items.sort(using: $0)
        }
        .font(.caption)
        .frame(width: 960, height: 540)
    }
}

struct ItemModel: Identifiable {
    var id: Int
    var title: String
    var age: Int
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

this is a working example of a Table sorted on Model.age, and support multi selection, I want single selection and open sheet on double click on a row, is that possible? also how do I get the selected item object?

thank you 🙏


Solution

  • You must change Set<Value.ID> for Value.ID for only one row selection, and make TapGesture in Text.

    @State private var selection = Set<ItemModel.ID>() // <-- Use this for multiple rows selections
    
    @State private var selection : ItemModel.ID? // <--- Use this for only one row selection
    
    struct ContentView: View {
        
        @State private var items: [ItemModel] = Array(0...100).map { ItemModel(id: $0, title: "item \($0)", age: $0) }
        //@State private var selection = Set<ItemModel.ID>() <-- Use this for multiple rows selections
        @State private var selection : ItemModel.ID? // <--- Use this for only one row selection
        @State private var sorting = [KeyPathComparator(\ItemModel.age)]
        @State private var showRow = false
        
        var editRow: some View {
            VStack {
                Text(items[selection!].title)
                    .font(.title)
                Text("Selected: \(selection.debugDescription)")
                 Button("Dismiss") {
                    showRow.toggle()
                 }.padding()
            }
            .frame(minWidth:400, minHeight: 400)
        }
        
        var body: some View {
            VStack {
                Table(items, selection: $selection, sortOrder: $sorting) {
                    TableColumn("id", value: \.id) {
                        Text("\($0.id)")
                            .onTapGesture(count: 2, perform: {
                                if selection != nil {
                                    showRow.toggle()
                                }
                            })
                    }
                    TableColumn("title") { itemModel in
                        Text(itemModel.title)
                            .onTapGesture(count: 2, perform: {
                                if selection != nil {
                                    showRow.toggle()
                                }
                            })
                    }
                    TableColumn("age", value: \.age) { Text("\($0.age)") }
                }
                .onChange(of: sorting) {
                    items.sort(using: $0)
                }
                .font(.caption)
                .frame(width: 960, height: 540)
            }
            .sheet(isPresented: $showRow) {
                editRow
            }
        }
    }