SwiftUI中NavigationSplitView导航状态持久化问题
问题现象
使用带侧边栏的NavigationSplitView,侧边栏通过NavigationLink跳转到包含NavigationStack、自有NavigationLinks、NavigationDestinations及导航路径的HomeView。尝试用@SceneStorage序列化保存路径,实现切换侧边栏时保留视图导航状态,但出现以下错误提示:
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.
导航仅能正常工作一次,且仅在首次通过侧边栏导航前有效。
预期流程
通过侧边栏进入HomeView,从HomeView跳转到Test4NavView,切换侧边栏到其他视图后返回HomeView,仍停留在Test4NavView。
相关代码
MainView
var body: some View { NavigationSplitView( sidebar: { SidebarView() }, detail: { HomeView()} ) } }
侧边栏导航项(SidebarNavigationItem)
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(需保留导航状态的视图)
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) } } }
Test4NavView
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) } } }
内容的提问来源于stack exchange,提问作者Bukinski

