Swift 2.2中NSMenuItem的选择器

4

我有一个简单的单文件菜单栏应用程序,使用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 - onmyway133
3个回答

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 启用它,则关于函数不会执行。 - lutrekubej
我编辑了答案。感谢指出从简单的Swift文件运行应用程序的想法。 - vadian
谢谢!我受到这个的启发:http://czak.pl/2015/09/23/single-file-cocoa-app-with-swift.html - lutrekubej
我也阅读了这篇文章,以找出如何处理Swift文件。 - vadian
1
需要注意的一点是,无论目标是什么,它都需要在某个地方有强引用。如果对象不在内存中,则无法引用,因此也无法访问。 - leogdion

0

更新操作

aboutMenuItem.action = Selector("about")

并添加

aboutMenuItem.enabled = true

谢谢,但它不起作用。它显示一个警告: “警告:使用'#selector'代替显式构造'Selector'”但更重要的是,即使添加了“aboutMenuItem.enabled = true”,该项仍然被禁用。 - lutrekubej
在这种情况下,“aboutMenuItem.enabled = true”没有效果,因为隐式验证具有更高的优先级。 - vadian

0
考虑一下这个问题:
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()

谢谢,这使“关于”项目启用了,但单击它不会执行关于函数。 - lutrekubej
我已经更新了答案。对我来说,这很好用。显然原因是内存管理。我记录了StatusBarApp对象的deinit并确定在您的情况下该应用程序对象立即被销毁。 - Igor B.
谢谢!我已经选择了另一个答案,但这个也可以。 - lutrekubej
欢迎 :) @vadian。指出应用程序委托设置并不重要是有道理的。根本原因在于内存管理。 - Igor B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接