Reputation: 712
I'm currently building a macOS App with SwiftUI
(no Catalyst) that is supposed to have a Sidebar and a single View to the right of it.
NavigationView {
List {
...
}
.listStyle(SidebarListStyle())
HomeView()
}
My Home View has a NavigationLink
inside of it, pointing to another DetailView
.
struct HomeView: View {
var body: some View {
NavigationLink("DetailView", destination: Text("This is the DV"))
}
}
This NavigationLink always appears as disabled and only works when I add another Column to the NavigationView
. I don't want another Column, but rather the NavigationLink
replacing the HomeView
with the DetailView
.
Is there any way to achieve this?
Upvotes: 5
Views: 1947
Reputation: 712
So apparently SwiftUI 2 does not support pushing views on to the Navigation Stack on macOS yet. However, I found this package that helps to resolve the issue:
github.com/lbrndnr/StackNavigationView
Upvotes: 2
Reputation: 14955
NavigationLinks always open a detail view from the current "column" of the navigation view, so if your navigation link is rendered as a child view of HomeView then it will try to open as a detail view of HomeView (the missing third column). If you want a view to replace the HomeView the intended way then the user should select something from the List. If you're trying to programmatically select a NavigationLink that already exists in your list then you should do so by changing state within the HomeView of a variable that is bound to the selected item of the list or the selection of the NavigationLink within the list. Here's a complete working example that does both within the ContentView.swift of a new MacOS SwiftUI Xcode project
struct HomeView: View {
@Binding var selectedItem: String?
var body: some View {
Button("Hello") {
selectedItem = "Thing2"
}
}
}
struct ContentView: View {
@State private var selectedItem: String?
private let items = ["Thing1", "Thing2"]
var body: some View {
NavigationView {
List(selection: $selectedItem) {
ForEach(items, id: \.self) {item in
NavigationLink(
destination: Text(item),
tag: item,
selection: $selectedItem
) {
Text(item)
}
}
}
HomeView(selectedItem: $selectedItem)
}
}
}
Here is the application displaying the HomeView
And here is the application displaying the selected thing after pressing the button
If you don't want to show anything selected in the list after navigating the view, but still want to use a navigation link to maintain the integrity of the navigation within the NavigationView then you could technically put a hidden navigation link in the list
NavigationView {
List(selection: $selectedItem) {
ForEach(items, id: \.self) {item in
NavigationLink(
destination: Text(item),
tag: item,
selection: $selectedItem
) {
Text(item)
}
}
NavigationLink(
destination: Text("Sneaky"),
tag: "Sneaky",
selection: $selectedItem
) {
Text("")
}.hidden()
}
HomeView(selectedItem: $selectedItem)
}
In that case make sure your button also selects the sneaky destination link
Button("Hello") {
selectedItem = "Sneaky"
}
Upvotes: 0