SwiftUI Mac端ToolbarItem在NavigationView分栏间异常跳转问题
解决SwiftUI Mac应用双侧边栏ToolbarItem异常跳转问题
问题根源
你当前的实现是通过切换不同的NavigationView实例来适配侧边栏状态(NoSidebars/LeftSidebars等),每次状态变化都会重建整个导航视图及附属的工具栏。这种方式会让SwiftUI无法正确跟踪ToolbarItem的归属,加上每个子视图单独设置toolbar,最终导致按钮跳转异常。
正确解决方案:使用原生NavigationSplitView
SwiftUI 3.0+提供的NavigationSplitView专门用于多栏布局(完美匹配Xcode的双侧边栏模式),无需切换整个视图,仅通过状态控制栏的显示/隐藏,从根源避免Toolbar异常。
步骤1:调整状态管理
更新你的MenuBarViewModel,直接使用NavigationSplitViewVisibility来控制栏状态:
import SwiftUI class MenuBarViewModel: ObservableObject { static let shared = MenuBarViewModel() // 初始显示所有侧边栏 @Published var columnVisibility: NavigationSplitViewVisibility = .all }
步骤2:重构ContentView为单NavigationSplitView
移除所有分栏视图(NoSidebars/LeftSidebars等),用单个NavigationSplitView实现布局,并统一设置工具栏:
struct ContentView: View { @ObservedObject var mbvm = MenuBarViewModel.shared var body: some View { NavigationSplitView(columnVisibility: $mbvm.columnVisibility) { // 左侧侧边栏视图 ButtonToolbarView() .navigationTitle("左侧面板") } content: { // 中间主内容视图 PreView() .navigationTitle("主内容") } detail: { // 右侧检查器视图 InspectorView() // 替换为你的右侧检查器实现 .navigationTitle("检查器") } .toolbar { ToolbarItemGroup(placement: .primaryAction) { // 左侧侧边栏切换按钮 Button { if mbvm.columnVisibility.contains(.sidebar) { mbvm.columnVisibility.remove(.sidebar) } else { mbvm.columnVisibility.insert(.sidebar) } } label: { Image(systemName: "sidebar.leading") .font(.system(size: 17)) } // 右侧检查器切换按钮 Button { if mbvm.columnVisibility.contains(.detail) { mbvm.columnVisibility.remove(.detail) } else { mbvm.columnVisibility.insert(.detail) } } label: { Image(systemName: "sidebar.trailing") .font(.system(size: 17)) } } } .windowToolbarStyle(UnifiedWindowToolbarStyle(showsTitle: false)) .windowStyle(HiddenTitleBarWindowStyle()) } }
步骤3:移除子视图中的独立toolbar
删除NoSidebars、LeftSidebars等视图内的.toolbar修饰符,所有工具栏按钮统一由顶层的NavigationSplitView管理。
额外优化
- 可以直接使用系统原生的侧边栏切换按钮样式:给按钮添加
.sidebarToggleStyle(.sidebar),让按钮行为与系统一致。 - 如果需要自定义侧边栏宽度,可在左侧/右侧视图上添加
.frame(minWidth: 100, idealWidth: 150, maxWidth: 300)来控制。
内容的提问来源于stack exchange,提问作者newb
相关产品推荐
相关产品推荐

