【发布时间】:2020-12-26 20:31:47
【问题描述】:
我在 MacOS 上使用 SwiftUI 创建了一个非常简单的应用程序。默认有一个菜单项show tab bar。我该如何删除这个?在这个应用程序中有标签是没有意义的。
我发现以下回答了相同的问题,但适用于旧版本的 Swift,而不适用于 SwiftUI:How do I disable the Show Tab Bar menu option in Sierra apps?
【问题讨论】:
我在 MacOS 上使用 SwiftUI 创建了一个非常简单的应用程序。默认有一个菜单项show tab bar。我该如何删除这个?在这个应用程序中有标签是没有意义的。
我发现以下回答了相同的问题,但适用于旧版本的 Swift,而不适用于 SwiftUI:How do I disable the Show Tab Bar menu option in Sierra apps?
【问题讨论】:
SwiftUI 中的等价物与 Swift 中的等价物相同(由于某种原因,该帖子中未提及)。要从应用程序的任何窗口中完全删除这些项目,您可以在应用程序委托中将布尔值 allowsAutomaticWindowTabbing 设置为 false
func applicationWillFinishLaunching(_ notification: Notification) {
NSWindow.allowsAutomaticWindowTabbing = false
}
【讨论】:
我也在寻找这个问题的答案,结果如下:
默认情况下 - 正如您已经提到的 - 显示/隐藏选项卡处于活动状态:
NSWindow 上有一个名为tabbingMode 的属性,它允许我们通过将其设置为.disallowed 来进行控制。但我的问题是:在 SwiftUI 2 生命周期应用程序中,我如何才能掌握应用程序的窗口?
好吧,有NSApplication.shared.windows,所以我的第一个(不工作!!)尝试是修改我的@main-App 结构中的所有窗口(因为我已经阻止了新窗口已创建,应该足够了):
import SwiftUI
@main
struct DQ_SyslogApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
let _ = NSApplication.shared.windows.map { $0.tabbingMode = .disallowed }
}
}
.commands {
CommandGroup(replacing: .newItem) {} //remove "New Item"-menu entry
}
}
}
很遗憾,这不起作用,因为 NSApplication.shared.windows 在 .onAppear 中为空。
我的下一步是在我的 SwiftUI 2 生命周期中引入一个 AppDelegate,它实现了applicationDidFinishLaunching(_:)...
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
print("Info from `applicationDidFinishLaunching(_:): Finished launching…")
let _ = NSApplication.shared.windows.map { $0.tabbingMode = .disallowed }
}
}
...并将这个 AppDelegate 引入应用程序:
import SwiftUI
@main
struct DQ_SyslogApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
.commands {
CommandGroup(replacing: .newItem) {} //remove "New Item"-menu entry
}
}
}
这对我有用:
虽然我希望完全删除菜单条目,但这至少可以防止用户使用 OP 要求的选项卡。
如果有人碰巧知道隐藏这些条目的解决方案,请告诉我们。我找不到代表这些菜单的CommandGroupPlacement...
【讨论】:
感谢@JuJoDi
如果您使用的是 SwiftUI 生命周期 (Scene),您可以执行以下操作:
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
NSWindow.allowsAutomaticWindowTabbing = false
}
}
}
}
【讨论】:
我在阅读这篇文章后发现了如何删除“编辑”菜单项
https://steipete.com/posts/top-level-menu-visibility-in-swiftui/
func applicationDidFinishLaunching(_ notification: Notification) {
NSWindow.allowsAutomaticWindowTabbing = false
if let mainMenu = NSApp .mainMenu {
DispatchQueue.main.async {
if let edit = mainMenu.items.first(where: { $0.title == "Edit"}) {
mainMenu.removeItem(edit);
}
}
}
}
【讨论】:
发布版本的结果:
查看带有 cmets "HERE" 的地方:
@main
struct MyFirstApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
init() {
// HERE
disallowTabbingMode()
}
@SceneBuilder
var body: some Scene {
WindowGroup {
AppMainView()
}
.commands {
//MenuLine_MyFirstApp_CustomAbout()
// HERE
MenuLine_File_NewWindow_Disable()
//MenuLine_Help_SupportEmail()
}
}
}
以及理解 SwiftUI 中菜单的方法 + 奖励
// Set Custom About window instead of default
fileprivate func MenuLine_MyFirstApp_CustomAbout() -> CommandGroup<Button<Text>> {
CommandGroup(replacing: CommandGroupPlacement.appInfo) {
Button("About") { appDelegate.showAboutWnd() }
}
}
//Add some menu button into Help menu
fileprivate func MenuLine_Help_SupportEmail() -> CommandGroup<Button<Text>> {
CommandGroup(after: CommandGroupPlacement.help) {
Button("Support Email") { NSWorkspace.shared.open("mailto:support@myfirstapp.com") }
}
}
// Disable "File -> New window" menu item (make it absent in release build)
fileprivate func MenuLine_File_NewWindow_Disable() -> CommandGroup<EmptyView> {
CommandGroup(replacing: .newItem) { }
}
fileprivate func disallowTabbingMode() {
NSWindow.allowsAutomaticWindowTabbing = false
}
【讨论】: