嵌入NavigationSplitView后NavigationStack的.searchable修饰符不显示
在iPad上,将带有.searchable修饰符的NavigationStack嵌入NavigationSplitView的详情列后,搜索栏无法正常显示,但单独使用SearchableView时功能正常。相关代码如下:
主视图代码
if UIDevice.current.userInterfaceIdiom == .pad { NavigationSplitView { List(navItems, id: \.self, selection: $selectedNavItem) { navItem in Text(navItem) } } detail: { if selectedNavItem == "Search" { SearchableView() } else { // … } } }
SearchableView代码
NavigationStack(path: $navPath) { VStack(alignment: .leading, spacing: 0) { // … } .navigationTitle("Search") } .searchable( text: self.$query, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search…" )
根据官方文档提示,.searchable需添加到NavigationSplitView的对应列视图上,但这种要求在允许嵌套NavigationStack的情况下显得不合理,且Apple Music明显采用了类似嵌套模式,因此想确认是否有遗漏的实现细节。
解决方案
方法一:将.searchable移到NavigationSplitView的详情列容器上
直接把.searchable修饰符应用到详情列中SearchableView的外层,让它关联到NavigationSplitView的详情导航栏:
if UIDevice.current.userInterfaceIdiom == .pad { NavigationSplitView { List(navItems, id: \.self, selection: $selectedNavItem) { navItem in Text(navItem) } } detail: { if selectedNavItem == "Search" { SearchableView() .searchable( text: $query, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search…" ) } else { // … } } }
方法二:将.searchable移到NavigationStack内部的根视图上
把.searchable放在NavigationStack内部的根视图(比如VStack)上,让它关联到NavigationStack自身的导航栏:
// SearchableView修改后代码 NavigationStack(path: $navPath) { VStack(alignment: .leading, spacing: 0) { // … } .navigationTitle("Search") .searchable( text: self.$query, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search…" ) }
原因说明
SwiftUI中,.searchable的显示依赖于它所附着的视图是否拥有活跃的导航栏上下文。在NavigationSplitView结构里,详情列的顶层导航栏属于NavigationSplitView本身,嵌套在内部的NavigationStack的.searchable无法正确将搜索栏附着到外层导航栏上。Apple Music的实现大概率是采用了第一种方法,将搜索栏直接关联到NavigationSplitView的详情列容器,而非内部嵌套的NavigationStack。
内容的提问来源于stack exchange,提问作者Ronni
相关产品推荐
相关产品推荐

