【问题标题】:Hiding Edit Menu of a SwiftUI / MacOS app隐藏 SwiftUI / MacOS 应用程序的编辑菜单
【发布时间】:2022-06-15 06:25:18
【问题描述】:

我的 MacOS 应用程序没有任何文本编辑功能。如何隐藏自动添加到我的应用程序的Edit 菜单?我更喜欢在 SwiftUI 中执行此操作。

我希望下面的代码应该可以工作,但事实并非如此。

@main
struct MyApp: App {

var body: some Scene {
    WindowGroup {
        ContentView()
    }.commands {
        CommandGroup(replacing: .textEditing) {}
    }
}

}

【问题讨论】:

    标签: swift macos swiftui


    【解决方案1】:

    据我所知,你不能隐藏整个菜单,你可以隐藏其中的元素组:

        .commands {
            CommandGroup(replacing: .pasteboard) { }
            CommandGroup(replacing: .undoRedo) { }
        }
    

    【讨论】:

    • 文件菜单呢?据Apple称可以删除。 developer.apple.com/design/human-interface-guidelines/macos/…
    • 使用 CommandGroup(replacing: .saveItem) { }CommandGroup(replacing: .newItem) { } 你会得到一个空的文件菜单。但我看不到完全摆脱它的方法。不幸的是,macOS 的 SwiftUI 仍然缺乏很多 ....
    【解决方案2】:

    对于原生 (Cocoa) 应用程序

    可以使用NSApplicationDelegate 删除应用程序菜单。这种方法可能会在未来的 macOS 版本中失效(例如,如果 Edit 菜单的位置发生变化),但目前确实有效:

    class MyAppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
      let indexOfEditMenu = 2
       
      func applicationDidFinishLaunching(_ : Notification) {
        NSApplication.shared.mainMenu?.removeItem(at: indexOfEditMenu)
      }
    }
    
    
    @main
    struct MyApp: App {
      @NSApplicationDelegateAdaptor private var appDelegate: MyAppDelegate
    
      var body: some Scene {
        WindowGroup {
          ContentView()
        }.commands {
          // ...
        }
      }
    }
    

    对于 Catalyst (UIKit) 应用程序

    对于基于 Catalyst 的 macOS 应用程序,该方法与上述方法类似,只是使用了派生自 UIResponderUIApplicationDelegate

    class MyAppDelegate: UIResponder, UIApplicationDelegate, ObservableObject {
       override func buildMenu(with builder: UIMenuBuilder) {
          /// Only operate on the main menu bar.
          if builder.system == .main {
             builder.remove(menu: .edit)
          }
       }
    }
    
    
    @main
    struct MyApp: App {
      @UIApplicationDelegateAdaptor private var appDelegate: MyAppDelegate
    
      var body: some Scene {
        WindowGroup {
          ContentView()
        }.commands {
          // ...
        }
      }
    }
    

    【讨论】:

      【解决方案3】:

      当 SwiftUI 更新窗口正文时,当前的建议对我来说失败了。

      解决方案:

      使用 KVO 并观察 NSApp 以了解 \.mainMenu 上的更改。在 SwiftUI 轮到你之后,你可以删除任何你想要的东西。

      @objc
      class AppDelegate: NSObject, NSApplicationDelegate {
          
          var token: NSKeyValueObservation?
          
          func applicationDidFinishLaunching(_ notification: Notification) {
              
              // Remove a single menu
              if let m = NSApp.mainMenu?.item(withTitle: "Edit") {
                  NSApp.mainMenu?.removeItem(m)
              }
      
              // Remove Multiple Menus
              ["Edit", "View", "Help", "Window"].forEach { name in
                  NSApp.mainMenu?.item(withTitle: name).map { NSApp.mainMenu?.removeItem($0) }
              }
              
              
      
              // Must remove after every time SwiftUI re adds
              token = NSApp.observe(\.mainMenu, options: .new) { (app, change) in
                  ["Edit", "View", "Help", "Window"].forEach { name in
                      NSApp.mainMenu?.item(withTitle: name).map { NSApp.mainMenu?.removeItem($0) }
                  }
      
                  // Remove a single menu
                  guard let menu = app.mainMenu?.item(withTitle: "Edit") else { return }
                  app.mainMenu?.removeItem(menu)
              }
          }
      }
      
      struct MarblesApp: App {
          @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
      
          var body: some View { 
              //... 
          }
      }
      

      想法:

      SwiftUI 要么存在错误,要么他们真的不希望您删除 NSApp.mainMenu 中的顶级菜单。 SwiftUI 似乎重置了整个菜单,目前无法覆盖或自定义大多数细节(Xcode 13.4.1)。 CommandGroup(replacing: .textEditing) { }-esque 命令不允许您删除或清除整个菜单。分配一个新的NSApp.mainMenu 只会在 SwiftUI 需要时被破坏,即使你没有指定任何命令。

      这似乎是一个非常脆弱的解决方案。应该有办法告诉 SwiftUI 不要触摸NSApp.mainMenu 或启用更多自定义。或者 SwiftUI 似乎应该检查它是否拥有上一个菜单(菜单项是 SwiftUI.AppKitMainMenuItem)。或者我错过了他们提供的一些工具。希望这在 WWDC 测试版中得到修复?

      (在带有 Swift 5 的 Xcode 13.4.1 中,针对不带 Catalyst 的 macOS 12.3。)

      【讨论】:

        猜你喜欢
        • 2021-02-13
        • 2020-05-05
        • 1970-01-01
        • 2022-01-26
        • 2021-02-25
        • 2023-01-21
        • 1970-01-01
        • 2023-04-01
        • 1970-01-01
        相关资源
        最近更新 更多