如何让我的应用程序表现得像我正在使用 Swift 在运行时更改 Application is agent(UIElement)?
Posted
技术标签:
【中文标题】如何让我的应用程序表现得像我正在使用 Swift 在运行时更改 Application is agent(UIElement)?【英文标题】:How can I make my app behave like I'm changing Application is agent(UIElement) at runtime using Swift? 【发布时间】:2018-06-26 06:22:30 【问题描述】:我正在编写一个 Mac 应用程序,它是菜单栏右侧的 NSPopover
(Application is agent(UIElement)
设置为 YES
)。我允许用户通过单击并向下拖动来分离弹出框,这会将应用程序置于窗口内。这工作正常;但是,当应用程序被拖出菜单栏并变成一个窗口时,我希望我的应用程序的图标出现在 Dock 中,并在菜单栏的左侧显示应用程序特定的菜单,就好像Application is agent(UIElement)
设置为 NO
。相反,当窗口关闭并且应用程序返回到菜单栏中的弹出窗口时,我希望我的应用程序的图标从 Dock 中消失,并且不再在菜单栏的左侧显示应用程序特定的菜单 (@987654327 @ 设置回 YES
)。
来自this question,我了解到在运行时更改Application is agent(UIElement)
是不可能的。然而,给出的答案是在 Objective-C 中,最后一个函数似乎从 OS X 10.9 开始贬值。如何使我的应用程序具有与在运行时使用 Swift 更改 Application is agent(UIElement)
相同的行为?
我知道在windowDidBecomeMain
中会显示应用程序图标/菜单栏菜单,在windowWillClose
中会发生隐藏应用程序图标/菜单栏菜单。
谢谢。
【问题讨论】:
【参考方案1】:我花了很多时间反复试验,但我终于弄明白了。而不是使用Application is agent(UIElement)
,而是使用NSApp.setActivationPolicy
。现在这是我的代码。在 App Delegate 中:
var isWindow = false
class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
let popover = NSPopover()
func applicationDidFinishLaunching(_ aNotification: Notification)
// Insert code here to initialize your application
NSApp.setActivationPolicy(.accessory)
if let button = statusItem.button
button.image = NSImage(named: "StatusBarImage")
button.action = #selector(togglePopover(_:))
popover.contentViewController = MainViewController.loadController()
popover.delegate = self
popover.animates = false
popover.behavior = .transient
@objc func togglePopover(_ sender: Any?)
if popover.isShown == true
popover.performClose(sender)
else if detachedWindowController.window!.isVisible
detachedWindowController.window?.setIsVisible(false)
isWindow = true
else if isWindow == true
detachedWindowController.window?.setIsVisible(true)
else
if let button = statusItem.button
popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
lazy var detachedWindowController: DetachedWindowController =
let detachedWindowController = DetachedWindowController(windowNibName: "DetachedWindowController")
detachedWindowController.contentViewController = MainViewController.loadController()
return detachedWindowController
()
func popoverShouldDetach(_ popover: NSPopover) -> Bool
return true
func detachableWindow(for popover: NSPopover) -> NSWindow?
return detachedWindowController.window
在DetachedWindowController
:
class DetachedWindowController: NSWindowController, NSWindowDelegate
@IBOutlet var detachedWindow: NSWindow!
override func windowDidLoad()
super.windowDidLoad()
detachedWindow.delegate = self
func windowWillClose(_ notification: Notification)
isWindow = false
NSApp.setActivationPolicy(.accessory)
func windowDidBecomeMain(_ notification: Notification)
if NSApp.activationPolicy() == .accessory
NSApp.setActivationPolicy(.regular)
【讨论】:
【参考方案2】:此外,如果您在切换到常规后无法显示菜单和停靠图标,则可能需要执行以下操作。对于较旧的 Mac OS 版本,这绝对是必需的。
// needed to activate menu
NSArray *dockAppA = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.loginwindow"];
NSRunningApplication *dock = [dockAppA firstObject];
[dock activateWithOptions:NSApplicationActivateIgnoringOtherApps];
NSArray *dockAppB = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"myAppBundleIdentifier"];
NSRunningApplication *myApp = [dockAppB firstObject];
[myApp activateWithOptions:NSApplicationActivateIgnoringOtherApps];
【讨论】:
以上是关于如何让我的应用程序表现得像我正在使用 Swift 在运行时更改 Application is agent(UIElement)?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Linux 中获取箭头键并在键盘上输入键以表现得像 Windows 7
BindingList<T>.Sort() 表现得像 List<T>.Sort()
如何在 Swift 中将触摸事件发送到 nextResponder