Handling single selection action in multi-selection SwiftUI Table

I have a SwiftUI Table on iPadOS that supports multiple selection and contains rows representing documents that can be opened. I want to be able to select multiple rows from edit mode or with keyboard modifiers for batch operations, but a regular tap on a single item should open it and push it onto the navigation stack.

Rows are highlighted when I tap on them, but the table's selection isn't modified and I can't figure out how to respond to that action. There's nowhere for me to put a NavigationLink because I'm only providing views for each column and not for the row itself. I could also push onto the navigation stack manually if I could respond to the action, but I don't see any API for doing so.

I've tried using .onChange(of: selection) and checking that the selection only contains a single element, but single taps on rows don't modify the selection, and even if they did, this logic would trigger incorrectly when adding the first item to the selection in edit mode for example.

Is there something I'm overlooking, or is this not possible with SwiftUI tables currently?

Accepted Answer

I recently came across a new modifier in macOS Ventura called contextAction(forSelectionType:action:) and seems to do what you are describing. The closure that is run can be used to perform the navigation or whatever you need to happen.

I'm currently on Monterey so I don't know how well it works on macOS, but I did try it out on iOS 16. Multi-selection still works when in edit mode, but when edit mode is inactive, tapping on a row performs the closure.

Hopefully this helps, and when you try it out on Ventura it works.

Looks like in beta 5 the contextAction modifier has been removed and merged with contextMenu.

The new modifier is contextMenu(forSelectionType:menu:primaryAction:).

Handling single selection action in multi-selection SwiftUI Table
 
 
Q