隐藏 SwiftUI / MacOS 应用程序的编辑菜单
我的 MacOS 应用程序没有任何文本编辑功能。如何隐藏自动添加到我的应用程序中的编辑
菜单?我更喜欢在 SwiftUI 中执行此操作。
我希望下面的代码应该可以工作,但事实并非如此。
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}.commands {
CommandGroup(replacing: .textEditing) {}
}
}
}
My MacOS app doesn't have any text editing possibilities. How can I hide the Edit
menu which is added to my app automatically? I'd prefer to do this in SwiftUI.
I would expect the code below should work, but it doesn't.
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}.commands {
CommandGroup(replacing: .textEditing) {}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
据我所知,您无法隐藏整个菜单,您可以隐藏其中的元素组:
To my knowledge you cannot hide the whole menu, you can just hide element groups inside of it:
当 SwiftUI 更新窗口主体时,当前的建议对我来说失败了。
解决方案:
使用 KVO 并观察
NSApp
上\.mainMenu
的更改。轮到 SwiftUI 后,您可以删除任何您想要的内容。想法:
SwiftUI 要么有错误,要么他们真的不希望您删除
NSApp.mainMenu
中的顶级菜单。 SwiftUI 似乎重置了整个菜单,目前无法覆盖或自定义大多数细节(Xcode 13.4.1)。CommandGroup(replacing: .textEditing) { }
式命令不允许您删除或清除整个菜单。即使您没有指定任何命令,当 SwiftUI 需要时,分配新的 NSApp.mainMenu 也会被破坏。这似乎是一个非常脆弱的解决方案。应该有一种方法告诉 SwiftUI 不要触摸 NSApp.mainMenu 或启用更多自定义。或者 SwiftUI 似乎应该检查它是否拥有以前的菜单(菜单项是 SwiftUI.AppKitMainMenuItem )。或者我缺少他们提供的一些工具。希望这个问题能在 WWDC 测试版中得到解决吗?
(在带有 Swift 5 的 Xcode 13.4.1 中,针对 macOS 12.3,没有 Catalyst。)
The current suggestions failed for me when SwiftUI updated the body of a window.
Solution:
Use KVO and watch the
NSApp
for changes on\.mainMenu
. You can remove whatever you want after SwiftUI has its turn.Thoughts:
SwiftUI either has a bug or they really don't want you to remove the top level menus in
NSApp.mainMenu
. SwiftUI seems to reset the whole menu with no way to override or customize most details currently (Xcode 13.4.1). TheCommandGroup(replacing: .textEditing) { }
-esque commands don't let you remove or clear a whole menu. Assigning a newNSApp.mainMenu
just gets clobbered when SwiftUI wants even if you specify no commands.This seems like a very fragile solution. There should be a way to tell SwiftUI to not touch the
NSApp.mainMenu
or enable more customization. Or it seems SwiftUI should check that it owned the previous menu (the menu items areSwiftUI.AppKitMainMenuItem
). Or I'm missing some tool they've provided. Hopefully this is fixed in the WWDC beta?(In Xcode 13.4.1 with Swift 5 targeting macOS 12.3 without Catalyst.)
对于那些正在寻找任何更新的人 - 请查看我提出的这个问题(并自己回答):
SwiftUI 更新 mainMenu [已解决] kludgey
我解决这个问题的方法是把它位于
AppDelegate
applicationWillUpdate
函数的DispatchQueue.main.async
闭包中我花了 4 天的时间进行搜索和尝试:) - 通常只需更改 2 行代码即可
For those of you that are looking for any updates on this - have a look at this question that I asked (and answered myself):
SwiftUI Update the mainMenu [SOLVED] kludgey
The way I got around it was to put it in a
DispatchQueue.main.async
closure in theAppDelegate
applicationWillUpdate
functionIt took me a good 4 days of searching and attempting things :) - typical that it came down to a 2 line code change
对于本机 (Cocoa) 应用程序
可以使用
NSApplicationDelegate
删除应用程序菜单。此方法可能会在未来的 macOS 版本中中断(例如,如果编辑菜单的位置发生更改),但目前确实有效:对于 Catalyst (UIKit) 应用程序
对于基于 Catalyst 的 macOS 应用程序,该方法是与上面类似,不同之处在于使用了从
UIResponder
派生的UIApplicationDelegate
:For native (Cocoa) apps
It is possible to remove application menus using an
NSApplicationDelegate
. This approach may break in future macOS versions (e.g. if the position of the Edit menu were to change), but does currently work:For Catalyst (UIKit) apps
For Catalyst-based macOS apps, the approach is similar to that above, except that a
UIApplicationDelegate
deriving fromUIResponder
is used:您应该能够通过稍微修改@waggles 的答案来隐藏整个菜单。
You should be able to hide whole menus by modifying @waggles's answer a bit.
建议 KVO 的答案和建议响应应用程序生命周期方法(
applicationDidFinishLaunching
除外)的答案都不适合我(结果要么是小故障、延迟,要么有时根本不起作用。)为我工作(针对 macOS 14.0)只是隐藏有问题的主菜单项:
然后在您的 SwiftUI
App
结构中:有趣的事实:同样适用于任何主菜单的子菜单项。
显然仍然不太好,必须通过名称找到菜单项,当用户使用非英语版本的 macOS 时,这显然会破坏此实现......
改天我会死在那个山上。
Neither of the answers suggesting KVO nor answers suggesting responding to application lifecycle methods (other than
applicationDidFinishLaunching
) worked for me (the result was either glitchy, delayed or sometimes just plain wouldn't work.)What did end up working for me (targeting macOS 14.0) is just HIDING the offending main menu items:
and then in your
SwiftUI
App
struct:Fun fact: The same works with any of the main-menu's submenu-items.
Still obviously not great that menu items have to be found by name, which will obviously break this implementation when the user has a none-english version of macOS...
I'll die on that hill another day.