在macOS上的SwiftUI NavigationView中切换侧边栏

时间:2020-05-13 09:58:22

标签: swift macos swiftui appkit

我有一个带有NavigationView的macOS应用程序,并且希望在窗口的工具栏中具有默认的ToggleSidebar项。

当前,我将ToolbarItem的目标设置为toolbarWillAddItem(_)的{​​{1}}中的AppDelegate。

在我实施的AppDelegate内

NSToolbarDelegate

此解决方案目前正在运行。如果SwiftUI的实现将更改此中断。

那么如何更好地做到这一点?

4 个答案:

答案 0 :(得分:2)

在SwiftUI 2.0中,您可以将NSApp.keyWindow?.firstResponder?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)与工具栏按钮结合使用,如下所示:

.toolbar {
    ToolbarItem(placement: .navigation) {
        #if os(macOS)
        Button(action: toggleSidebar, label: {
            Image(systemName: "sidebar.left")
        })
        #endif
    }
}

func toggleSidebar() {
    #if os(macOS)
    NSApp.keyWindow?.firstResponder?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
    #endif
}

答案 1 :(得分:2)

从macOS Big Sur beta 4开始,您可以使用SwiftUI 2.0添加默认的边栏命令。

var body: some Scene {
    WindowGroup {
        NavigationView {
            Group {
                SidebarView()
                ContentView()
            }
        }
    }
    .commands {
        SidebarCommands()
    }
}

此代码将添加“切换边栏”快捷方式:

enter image description here

SidebarView代码:

var body: some View {
    List {
        ForEach(0..<5) { index in
            Text("\(index)")
        }
    }
    .listStyle(SidebarListStyle())
}

答案 2 :(得分:1)

我不为此使用NavigationView。请改用HSplitView,并使用https://stackoverflow.com/a/59228385/811010

中的隐藏标志

答案 3 :(得分:1)

虽然您可以尝试在 #selector(NSSplitViewController.toggleSidebar(_:))keyWindow?.contentViewController 上执行 keyWindow?.firstResponder?,但在某些情况下这似乎并不一致。

相反,您可以使用以下命令:

NSApp.sendAction(#selector(NSSplitViewController.toggleSidebar(_:)), to: nil, from: nil)

它将 toggleSidebar 选择器发送到第一个可以对其做出反应的对象,即当前窗口中唯一的侧边栏。这种行为有更好的记录on Apple's documentation website.


此方法是 SidebarCommands() 菜单项使用的默认实现。这是通过添加 Toggle Sidebar 菜单项找到的,然后像这样获取它的选择器:

let menu = NSApp.mainMenu!.items.first(where: { $0.title == "View" })!
let submenu = menu.submenu!.items.first(where: { $0.title == "Toggle Sidebar" })!
submenu.target // nil
submenu.action // #selector(toggleSidebar:)

这意味着它很可能比其他方法更一致(和支持)。