TL;DR:
I cannot have a list with a detail view and multiple selections on macOS.
In more detail:
For demonstration purposes of my issue, I made a small example project. The UI looks as follows:
This is the "app" when launched, with a list on top and a detail representation below. Because I am using the List's initialiser init(_:selection:rowContent:)
, where selection
is of type Binding<SelectionValue?>?
according to Apple's documentation, I get selecting items with the keyboard arrow keys for free.
Here's the complete code:
import SwiftUI
@main
struct UseCurorsInLisstApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(ViewModel())
}
}
}
class ViewModel: ObservableObject {
@Published var items = [Item(), Item(), Item(), Item(), Item()]
@Published var selectedItem: Item? = nil
}
struct Item: Identifiable, Hashable {
let id = UUID()
}
struct ContentView: View {
@EnvironmentObject var vm: ViewModel
var body: some View {
VStack {
List(vm.items, id: \.self, selection: $vm.selectedItem) { item in
VStack {
Text("Item \(item.id.uuidString)")
Divider()
}
}
Divider()
Group {
if let item = vm.selectedItem {
Text("Detail item \(item.id.uuidString)")
} else {
Text("No selection…")
}
}
.frame(minHeight: 200.0, maxHeight: .infinity)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Now, having had success with this so far, I figured being able to select more than one row would be useful, so I took a closer look into List(_:selection:rowContent:)
, where selection
is of type Binding<Set<SelectionValue>>?
. To be able to have a detail view, I just made a few minor changes to
the ViewModel
:
class ViewModel: ObservableObject {
@Published var items = [Item(), Item(), Item(), Item(), Item()]
@Published var selectedItem: Item? = nil
@Published var selectedItems: Set<Item>? = nil {
didSet {
if selectedItems?.count == 1, let item = selectedItems?.first {
selectedItem = item
}
}
}
}
and the ContentView
:
struct ContentView: View {
@EnvironmentObject var vm: ViewModel
var body: some View {
VStack {
List(vm.items, id: \.self, selection: $vm.selectedItems) { item in
VStack {
Text("Item \(item.id.uuidString)")
Divider()
}
}
Divider()
Group {
if vm.selectedItems?.count == 1, let item = vm.selectedItems?.first {
Text("Detail item \(item.id.uuidString)")
} else {
Text("No or multiple selection…")
}
}
.frame(minHeight: 200.0, maxHeight: .infinity)
}
}
}
The problem now is that I cannot select an item of the row any more, neither by clicking, nor by arrow keys. Is this a limitation I am running into or am I "holding it wrong"?