如何为macOS菜单栏应用程序启用自动启动?

问题描述 投票:0回答:1

我正在构建一个macOS应用程序,用于菜单栏,它应从系统启动时自动启动。我首先按照本教程this tutorial为基于窗口的标准macOS应用程序实现自动启动功能。我有

  • 在主项目(助手应用程序)中添加了新的目标
  • 将助手应用程序的skip install更改为yes
  • 将助手应用设置为仅后台应用
  • 向主应用程序添加了新的复制文件构建阶段,以将帮助程序应用程序复制到捆绑软件中
  • 链接ServiceManagement.framework
  • 在应用程序委托中实现了功能,该助手应用程序在系统启动时启动。启动后,它将启动主应用程序(有关更多信息或下面的源代码,请参见教程链接)

效果很好,该应用程序自动启动了:)因此,我开始更改项目,使主应用程序成为菜单栏应用程序。但是,该应用程序将无法自动启动:/有人对此有解决方案吗?

这里是主应用程序的应用程序委托的代码:

import Cocoa
import ServiceManagement

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)


func applicationDidFinishLaunching(_ aNotification: Notification) {

    statusItem.button?.title = "Test"
    statusItem.button?.target = self
    statusItem.button?.action = #selector(showWindow)


    // auto start
    let launcherAppId = "com.####.####Helper"
    let runningApps = NSWorkspace.shared.runningApplications
    let isRunning = !runningApps.filter { $0.bundleIdentifier == launcherAppId }.isEmpty

    SMLoginItemSetEnabled(launcherAppId as CFString, true)

    if isRunning {
        DistributedNotificationCenter.default().post(name: .killLauncher, object: Bundle.main.bundleIdentifier!)
    }
}

func applicationWillTerminate(_ aNotification: Notification) {
    // Insert code here to tear down your application
}

@objc func showWindow() {
    let storyboard = NSStoryboard(name: "Main", bundle: nil)
    guard let vc = storyboard.instantiateController(withIdentifier: "ViewController") as? ViewController else {
        fatalError("Unable to find main view controller")
    }

    guard let button = statusItem.button else {
        fatalError("Unable to find status item button")
    }

    let popover = NSPopover()
    popover.contentViewController = vc
    popover.behavior = .transient
    popover.show(relativeTo: button.bounds, of: button, preferredEdge: .maxY)

}


}

extension Notification.Name {
   static let killLauncher = Notification.Name("killLauncher")
}

这是助手应用程序的应用程序委托:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {



func applicationDidFinishLaunching(_ aNotification: Notification) {
    let mainAppIdentifier = "com.####.####"
    let runningApps = NSWorkspace.shared.runningApplications
    let isRunning = !runningApps.filter { $0.bundleIdentifier == mainAppIdentifier }.isEmpty

    if !isRunning {
        DistributedNotificationCenter.default().addObserver(self, selector: #selector(self.terminate), name: .killLauncher, object: mainAppIdentifier)

        let path = Bundle.main.bundlePath as NSString
        var components = path.pathComponents
        components.removeLast()
        components.removeLast()
        components.removeLast()
        components.append("MacOS")
        components.append("####") //main app name

        let newPath = NSString.path(withComponents: components)

        NSWorkspace.shared.launchApplication(newPath)
    }
    else {
        self.terminate()
    }
}

func applicationWillTerminate(_ aNotification: Notification) {
    // Insert code here to tear down your application
}

@objc func terminate() {
    NSApp.terminate(nil)
}


}

extension Notification.Name {
  static let killLauncher = Notification.Name("killLauncher")
}

非常感谢您的帮助:)

swift macos cocoa menubar autostart
1个回答
1
投票

我的代码看起来几乎相同,除了我如何在助手应用程序中编写路径:

var pathComponents = (Bundle.main.bundlePath as NSString).pathComponents
pathComponents.removeLast()
pathComponents.removeLast()
pathComponents.removeLast()
pathComponents.removeLast()
let newPath = NSString.path(withComponents: pathComponents)
NSWorkspace.shared.launchApplication(newPath)

此外,如果我没记错的话,我必须确保Main.storyboard文件仍然具有带有应用程序对象和空主菜单的“应用程序场景”。

Application Scene

© www.soinside.com 2019 - 2024. All rights reserved.