I have a Problem preserving the Navigation state in my iOS App.
I have a NavigationSplitView (sidebar) with a list of NavigationLinks.
Each NavigationLink Navigates to a View With a NavigationStack and its own NavigationLinks with NavigationDestinations and a Navigation Path. I want to save the path using @ScenenStorage (after serialization) so when I navigate using the Sidebar, the NavigationStates of the Views are preserved. unfortunately I get the following message:
Note: Links search for destinations in any surrounding NavigationStack, then within the same column of a NavigationSplitView.
A NavigationLink is presenting a value of type “String” but there is no matching navigationDestination declaration visible from the location of the link. The link cannot be activated.
Note: Links search for destinations in any surrounding NavigationStack, then within the same column of a NavigationSplitView.
The Navigation only works once. And only before navigation via the Sidebar.
The code looks like this:
MainView:
var body: some View {
NavigationSplitView(
sidebar: { SidebarView() },
detail: { HomeView()}
)
}
}
NavigationLinks in the Sidebar:
struct SidebarNavigationItem<Destination: View>: View {
var option: String
var icon: String
var destination: Destination
let arsColors = ARSColors.shared
init(option: String, icon: String, destination: Destination) {
self.option = option
self.icon = icon
self.destination = destination
}
var body: some View {
NavigationLink(destination: destination) {
Label {
Text(option)
.foregroundColor(arsColors.primary)
} icon: {
Image(systemName: icon)
.foregroundColor(arsColors.highlight)
}
}
}
}
HomeView (this is the Navigation I want to preserve)
import SwiftUI
extension [String]: RawRepresentable {
public init?(rawValue: String) {
guard let data = rawValue.data(using: .utf8),
let result = try? JSONDecoder().decode([String].self, from: data)
else {
return nil
}
self = result
}
public var rawValue: String {
guard let data = try? JSONEncoder().encode(self),
let result = String(data: data, encoding: .utf8)
else {
return "[]"
}
return result
}
}
struct HomeView: View {
@SceneStorage("navPath") var navPath: [String] = []
var body: some View {
NavigationStack(path: $navPath) {
VStack {
Spacer()
HStack {
NavigationLink(value: navPath) {
WidgetView(widgetText: "Testnavigation")
}
Spacer()
WidgetView(widgetText: "Wifget2")
Spacer()
WidgetView(widgetText: "Widget3")
Spacer()
WidgetView(widgetText: "Widget4")
Spacer()
WidgetView(widgetText: "Widget5")
}
.padding(.all)
}
.navigationTitle("Home")
.navigationDestination(for: [String].self) {navPath in
Test4NavView(navPath: navPath)
}
}
.onAppear(){
print(navPath)
}
.onDisappear() {
print(navPath)
}
}
}
And finally the TestView
struct Test4NavView: View {
var navPath: [String]
@SceneStorage("input1") private var input1: String = ""
@SceneStorage("input2") private var input2: String = ""
@SceneStorage("input3") private var input3: String = ""
@SceneStorage("input4") private var input4: String = ""
var body: some View {
VStack(alignment: .center) {
TextField("Input 1", text: $input1)
TextField("Input 2", text: $input2)
TextField("Input 3", text: $input3)
TextField("Input 4", text: $input4)
}
.onAppear(){
print(navPath)
}
.onDisappear() {
print(navPath)
}
}
}
My Expectation is to Navigate to HomeView using the Sidebar then to Test4NavView from HomeView then to a different View using the Sidebar then back to HomeView using the Sidebar and I end up on Test4NavView