带有 contextMenu 的 macOS SwiftUI Table

macOS SwiftUI Table with contextMenu

使用 SwiftUI 的新 Table 容器,如何添加在按住 Control 键单击一行时出现的上下文菜单?

我可以将 contextMenu 修饰符添加到 TableColumn 的内容中,但是我必须将它添加到每个单独的列中。而且它只在特定文本上方有效,而不是在整行:

我尝试将修饰符添加到 TableColumn 本身,但它显示编译错误:

Value of type 'TableColumn<RowValue, Never, Text, Text>' has no member 'contextMenu'

这是我在源代码方面的内容,在 TableColumn 的内容中使用 contextMenu 修饰符:

struct ContentView: View {

    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Item.name, ascending: true)])
    private var items: FetchedResults<Item>

    @State
    private var sortOrder = [KeyPathComparator(\Item.name)]

    @State
    private var selection = Set<Item.ID>()

    var body: some View {
        NavigationView {
            Table(items, selection: $selection, sortOrder: $items.sortDescriptors) {
                TableColumn("Column 1") {
                    Text("Item at \([=12=].name!)")
                        .contextMenu {
                            Button(action: {}) { Text("Action 1") }
                            Divider()
                            Button(action: {}) { Text("Action 2") }
                            Button(action: {}) { Text("Action 3") }
                        }
                }

                TableColumn("Column 2") {
                    Text([=12=].id.debugDescription)
                }
            }
            .toolbar {
                ToolbarItem {
                    Button(action: addItem) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
            }

            if selection.isEmpty {
                Text("Select an item")
            } else if selection.count == 1 {
                Text("Selected \(items.first(where: { [=12=].id == selection.first! })!.id.debugDescription)")
            } else {
                Text("Selected \(selection.count)")
            }
        }
    }
}

那么,如何向 Table 中的整行添加上下文菜单?

您可以使用以下扩展制作单元格视图并将其用于每个列单元格,然后它可以在任何行位置点击

Text("Item at \([=10=].name!)")
    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) // << this !!
    .contentShape(Rectangle())                                            // << this !!
    .contextMenu {
        Button(action: {}) { Text("Action 1") }
        Divider()
        Button(action: {}) { Text("Action 2") }
        Button(action: {}) { Text("Action 3") }
    }