簡體   English   中英

如何為 macOS 菜單欄應用啟用自動啟動?

[英]How enable autostart for a macOS menu bar app?

我正在為菜單欄構建一個 macOS 應用程序,它應該隨着系統啟動而自動啟動。 我開始按照本教程的本教程為基於標准 window 的 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")
}

非常感謝您的幫助:)

我的代碼看起來幾乎相同,除了我如何在幫助應用程序中編寫路徑:

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 文件仍然具有“應用程序場景”,其中包含應用程序 object 和一個空的主菜單。

應用場景

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM