Reputation: 645
I have implemented a SwiftUI NavigationView
in macOS as follows:
struct App1: App {
var body: some Scene {
WindowGroup {
NavigationView {
SideBar()
Text("SCREEN 1")
}
}
}
}
where SideBar()
is a list of navigation links as follows:
struct SideBar: View {
var body: some View {
List {
NavigationLink(destination: SomeListView1()){
Text("Item1")
}
NavigationLink(destination: SomeListView2()){
Text("Item2")
}
NavigationLink(destination: SomeListView3()){
Text("Item3")
}
}
}
}
where SomeListViewn()
contains a list of items.
When I click different navigation links in the side bar, the related views are reloaded each time. For example, if I was to click Item1
and scroll to the bottom of the list of items in SomeListView1()
, then switch to Item2
and back to Item1
, SomeListView1()
is reloaded, i.e., it forgets its scroll position and re-initialises the view. I want the navigation views to remember their state so when you switch to different items in the sidebar and switch back, you can continue where you left off.
How can this be achieved?
Upvotes: 3
Views: 796
Reputation: 10346
Instead of using NavigationView
what you might want is to use a TabView with new .sidebarAdaptable
style like in this example:
struct TestView: View {
@State private var counter = 0
var title: String
var body: some View {
VStack {
Text("Title: \(title)")
Text("Counter: \(counter)")
Button("+1") {
counter += 1
}
}
}
}
struct ContentView: View {
var body: some View {
TabView {
TestView(title: "First tab")
.tabItem {
Label("First", systemImage: "f.circle")
}
TestView(title: "Second tab")
.tabItem {
Label("Second", systemImage: "s.circle")
}
TestView(title: "Third tab")
.tabItem {
Label("Third", systemImage: "t.circle")
}
}
.tabViewStyle(.sidebarAdaptable)
}
}
With this style TabView
on macOS will have a sidebar similarly as if you used a navigation view but the views inside it will keep state when you change the view which you can check with above example by tapping on the button and changing the view. Note however that this is only available on macOS 15+ and unfortunately afaik it only recently started to work correctly (on macOS 15.2 and lower it had a bug which caused it to not capture clicks correctly when clicked on the text, see: https://developer.apple.com/forums/thread/764764).
If you need to support lower version on macOS and therefore need to use NavigationView
/ NavigationSplitView
the simplest alternative solution would probably be to use @SceneStorage
to keep the state of each view (assuming you use unique views inside the sidebar that do not repeat).
Upvotes: 0