【问题标题】:Swift 2.2 selector in NSMenuItemNSMenuItem 中的 Swift 2.2 选择器
【发布时间】:2016-04-19 12:04:47
【问题描述】:

我在 swift 中有一个简单的单文件菜单栏应用程序:

import Cocoa

class StatusBarApp : NSObject {

  func buildMenu() {
    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
    statusItem.title = "StatusBarApp"

    let menu = NSMenu()

    let aboutMenuItem = NSMenuItem()
    aboutMenuItem.title = "About"
    aboutMenuItem.target = self
    aboutMenuItem.action = #selector(about)
    menu.addItem(aboutMenuItem)

    statusItem.menu = menu
  }

  func about() {
    print("XXX")
  }
}

NSApplication.sharedApplication()
StatusBarApp().buildMenu()
NSApp.run()

我无法将“关于”菜单栏项连接到 about() 函数。当我运行应用程序时,“关于”项被禁用。

如何在 Swift 2.2 中将选择器传递给菜单项操作?谢谢

【问题讨论】:

  • 在 Swift 4.2 中,只需添加 @objc func about

标签: swift cocoa nsmenuitem nsstatusbar


【解决方案1】:

选择器应该有一个参数(NSMenuItem 实例)

aboutMenuItem.action = #selector(StatusBarApp.about(_:))

...

func about(sender : NSMenuItem) {
   print("XXX")
}

编辑:

解决方案是将应用程序作为完整的 Cocoa 应用程序运行,包括其委托。
我添加了第二个菜单项来终止应用程序。

import Cocoa

class StatusBarApp : NSObject, NSApplicationDelegate {

  var statusItem : NSStatusItem!

  func applicationDidFinishLaunching(aNotification: NSNotification) {
    statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
    statusItem.title = "StatusBarApp"

    let menu = NSMenu()

    let aboutMenuItem = NSMenuItem(title:"About", action:#selector(StatusBarApp.about(_:)), keyEquivalent:"")
    aboutMenuItem.target = self
    let quitMenuItem = NSMenuItem(title:"Quit", action:#selector(StatusBarApp.quit(_:)), keyEquivalent:"")
    quitMenuItem.target = self
    menu.addItem(aboutMenuItem)
    menu.addItem(quitMenuItem)

    statusItem.menu = menu
  }

  func about(sender : NSMenuItem) {
    print("XXX")
  }

  func quit(sender : NSMenuItem) {
    NSApp.terminate(self)
  }
}

NSApplication.sharedApplication()
let statusBarApp = StatusBarApp()
NSApp.delegate = statusBarApp
NSApp.run()

【讨论】:

  • 谢谢,我试过这个改变,但没有任何影响。该项目仍被禁用。如果我使用menu.autoenablesItems = false 启用它,则不会执行 about 函数。
  • 我编辑了答案。感谢您指出从简单的 Swift 文件运行应用程序的想法
  • 我也读了这篇文章,了解如何处理 Swift 文件
  • 需要注意的一点是,无论目标是什么。 它需要在某个地方被强引用。如果对象不在内存中,它就不能被引用,因此也不能被访问。
【解决方案2】:

更新操作

aboutMenuItem.action = Selector("about")

并添加

aboutMenuItem.enabled = true

【讨论】:

  • 谢谢,但它不起作用。它显示一个警告:warning: use '#selector' instead of explicitly constructing a 'Selector' 但更重要的是,该项目仍然被禁用,即使添加了aboutMenuItem.enabled = true
  • aboutMenuItem.enabled = true 在这种情况下不起作用,因为隐式验证具有更高的优先级。
【解决方案3】:

考虑一下:

import Cocoa

class StatusBarApp : NSObject {

    func buildMenu() {
        let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
        statusItem.title = "StatusBarApp"

        let menu = NSMenu()

        let aboutMenuItem = NSMenuItem()
        aboutMenuItem.title = "About"
        aboutMenuItem.target = self
        aboutMenuItem.action = #selector(about)
        menu.addItem(aboutMenuItem)

        statusItem.menu = menu
    }

    func about() {
        print("XXX")
    }
}


let app = StatusBarApp()
NSApplication.sharedApplication()
app.buildMenu()
NSApp.run()

【讨论】:

  • 谢谢,这使“关于”项启用,但点击它不会执行关于功能。
  • 我已经更新了答案。这对我来说很好。显然原因是内存管理。我记录了 StatusBarApp 对象的 deinit 并确定应用程序对象在您的情况下立即被破坏。
  • 谢谢!我已经用不同的解决方案选择了不同的答案,但这也有效。
  • 欢迎 :) @vadian 有必要指出应用程序委托设置无关紧要。根本原因在于内存管理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多