SwiftUI 3列NavigationSplitView中.navigationDestination(isPresented:)失效问题
问题原因解析
1. navigationDestination(isPresented:) 的作用范围限制
navigationDestination(isPresented:destination:) 是绑定到当前视图所在的导航栈,而SwiftUI的NavigationSplitView的三个列(侧边栏、主栏、详情栏)各自维护独立的导航栈。
在你的代码中,第二个navigationDestination(isPresented: $showDetails)嵌套在第一个destination的视图里——这个视图属于侧边栏的导航栈,所以它的触发只会尝试在侧边栏的栈里推送新视图,不会关联到主栏到详情栏的导航逻辑。当你点击"Show details"按钮时,showDetails的状态变化仅作用于侧边栏的导航系统,自然无法触发详情栏的内容展示。
2. navigationDestination(for:) 为什么能正常工作
navigationDestination(for:destination:) 基于**导航路径(NavigationPath)**的全局匹配机制,整个NavigationSplitView共享同一个导航路径上下文。不管在哪个列触发导航动作(比如推送指定类型的对象到路径中),系统都会自动在对应的列栈中匹配并展示对应目的地视图,天然支持跨栏的连续导航。
补充:正确实现跨栏导航的思路
如果要保留isPresented风格的触发,需要把每个列的navigationDestination分别声明在对应列的根视图层级中,而非嵌套:
struct ContentView: View { @State private var columnVisibility = NavigationSplitViewVisibility.all @State private var showMaster = false @State private var showDetails = false var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { Button("Show master") { showMaster = true } .navigationDestination(isPresented: $showMaster) { Button("Show details") { showDetails = true } } } content: { EmptyView() .navigationDestination(isPresented: $showDetails) { Text("Detail") } } detail: { EmptyView() } } }
这样showDetails的绑定就关联到主栏的导航栈,点击按钮时就能正确触发详情栏的展示。
内容的提问来源于stack exchange,提问作者Peter Polakovic
相关产品推荐
相关产品推荐

