in a book club app I'm trying to write, I have a NavigationSplitView
which displays a list of readers in a selectable List
that gives the user access to each reader's comments on a given book. At the top of the list is a button "Book" that takes the user back to the book's main page:
struct ProjectView: View
{
@State private var readers: [Reader]
@State private var selectedReader: Reader?
init(readers: [Reader])
{
self.readers = readers
}
var body: some View
{
NavigationSplitView
{
List(selection: self.$selectedReader)
{
Button("Book")
{
self.selectedReader = nil
}
Divider()
ForEach (self.readers, id: \.self)
{
reader in Text(reader.name)
}
}
}
detail:
{
if let selectedReader = self.selectedReader
{
ReaderView(reader: selectedReader)
}
else
{
BookView()
}
}
#if os(macOS)
.navigationSplitViewColumnWidth(min: 180, ideal: 200)
#endif
.navigationTitle(self.project.name)
}
}
I'm trying to make it so that "Book" will select / highlight just as the reader names in the reader list do, you can see what I mean in this video:
https://youtube.com/shorts/__IA890FxG0?feature=share
Does anyone know how to accomplish this? Or is it even possible?
You should use a ReaderOrBook?
, since the selection can be either a reader, or "Book", or nothing is selected at all (nil
).
enum ReaderOrBook: Hashable {
case book
case reader(Reader)
// convenient property to convert a ReaderOrBook to a Reader
var asReader: Reader? {
if case let .reader(r) = self {
return r
}
return nil
}
}
Then you just need to tag
the list rows appropriately.
struct ProjectView: View {
// this should not be a @State since you want callers to pass in an array of readers
// if you want to mutate this in ProjectView, make it a @Binding instead
let readers: [Reader]
@State private var selectedReaderOrBook: ReaderOrBook?
var body: some View {
NavigationSplitView {
List(selection: self.$selectedReaderOrBook) {
Text("Book").tag(ReaderOrBook.book)
Divider()
ForEach (self.readers, id: \.self) { reader in
Text(reader.name)
.tag(ReaderOrBook.reader(reader))
}
}
} detail: {
// ...
}
}
}