我有以下代码:(可以复制粘贴到新的macOS项目中)
import Cocoa
import SwiftUI
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var statusBarItem: NSStatusItem!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let statusBar = NSStatusBar.system
statusBarItem = statusBar.statusItem(
withLength: NSStatusItem.squareLength)
statusBarItem.button?.title = ""
// Setting action
statusBarItem.button?.action = #selector(self.statusBarButtonClicked(sender:))
statusBarItem.button?.sendAction(on: [.leftMouseUp])
let statusBarMenu = NSMenu(title: "Status Bar Menu")
statusBarMenu.addItem(
withTitle: "Order an apple",
action: #selector(AppDelegate.orderAnApple),
keyEquivalent: "")
statusBarMenu.addItem(
withTitle: "Cancel apple order",
action: #selector(AppDelegate.cancelAppleOrder),
keyEquivalent: "")
// Setting menu
statusBarItem.menu = statusBarMenu
}
@objc func statusBarButtonClicked(sender: NSStatusBarButton) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp {
print("Right click!")
} else {
print("Left click!")
}
}
@objc func orderAnApple() {
print("Ordering a apple!")
}
@objc func cancelAppleOrder() {
print("Canceling your order :(")
}
}
实际行为:在左键和右键单击时都会打开菜单,但不会触发statusBarButtonClicked事件。删除此行后:
statusBarItem.menu = statusBarMenu
在左键单击时,statusBarButtonClicked被触发,菜单不会弹出(正如预期)
期望的行为:右键单击打开菜单,左键单击不打开菜单,触发操作。
我该如何实现?
编辑
在@red_menace的评论帮助下,我成功实现了期望的行为:
import Cocoa
import SwiftUI
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var statusBarItem: NSStatusItem!
var menu: NSMenu!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let statusBar = NSStatusBar.system
statusBarItem = statusBar.statusItem(
withLength: NSStatusItem.squareLength)
statusBarItem.button?.title = ""
// Setting action
statusBarItem.button?.action = #selector(self.statusBarButtonClicked(sender:))
statusBarItem.button?.sendAction(on: [.leftMouseUp, .rightMouseUp])
let statusBarMenu = NSMenu(title: "Status Bar Menu")
statusBarMenu.addItem(
withTitle: "Order an apple",
action: #selector(AppDelegate.orderAnApple),
keyEquivalent: "")
statusBarMenu.addItem(
withTitle: "Cancel apple order",
action: #selector(AppDelegate.cancelAppleOrder),
keyEquivalent: "")
// Setting menu
menu = statusBarMenu
}
@objc func statusBarButtonClicked(sender: NSStatusBarButton) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp {
statusBarItem.popUpMenu(menu)
} else {
print("Left click!")
}
}
@objc func orderAnApple() {
print("Ordering a apple!")
}
@objc func cancelAppleOrder() {
print("Canceling your order :(")
}
}
但是Xcode说在10.14中openMenu
函数已经被弃用,并告诉我要使用menu
属性。有没有一种方法可以使用新API实现所需的行为?
sendActionOn:
中添加NSRightMouseUpMask
,不要将菜单设置为状态栏项。然后,在操作方法中检查事件并使用popUpStatusItemMenu:
来显示菜单,如果事件是NSEventTypeRightMouseUp
。请注意,在Catalina中,这些方法中的几个已被弃用。 - red_menacepopUpMenu:
吗?我找不到popUpStatusItemMenu
。如果是这样,popUpMenu 可以使用,但在 10.14 中已被弃用。警告显示“改用 menu 属性”。 - bapafes482popUpStatusItemMenu
是 Obj-C 的写法,Swift 中应该使用popUpMenu
。在 Catalina 中,popUpMenu
和sendAction
已经被弃用,是 NSStatusMenu 的方法。虽然 NSButton 上有一个sendAction
方法,但是相当于popUpMenu
的东西应该是设置状态栏菜单并在操作方法中显示它(例如通过 NSControl 的performClick
),然后在完成后删除菜单,以免被用于状态栏项目的正常行为。我不太了解 Swift,无法提供一个好的示例。 - red_menace