Hello,
according to
https://footle.org/WeatherBar/
and
https://theswiftdev.com/2017/10/27/how-to-launch-a-macos-app-at-login/
I've developed a menu only app with start at login functionality:
In the main app AppDelegate.swift is as follows:
//
// AppDelegate.swift
// onlyText
//
// Created by Ralf Matz on 26.01.19.
// Copyright © 2019 Ralf Matz. All rights reserved.
//
import Cocoa
import ServiceManagement
extension Notification.Name {
static let killLauncher = Notification.Name("killLauncher")
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Check if the launcher app is started
let launcherAppId = "com.ralfmatz.LauncherApplication"
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!)
}
}
}
In an auxiliary View (I named the file PreferencesView.swift) for settings whether the app should start at login or not:
//
// PreferencesView.swift
// onlyText
//
// Created by Ralf Matz on 07.03.19.
// Copyright © 2019 Ralf Matz. All rights reserved.
//
import Cocoa
import ServiceManagement
class PreferencesView: NSView {
// Bundle identifier of the auxiliary loader app
let helperBundleIdentifier = "com.ralfmatz.LauncherApplication"
@IBOutlet weak var checkBoxItem: NSButton!
@IBAction func startAtLogin(_ sender: NSButton) {
if(checkBoxItem.state == NSControl.StateValue.on){
SMLoginItemSetEnabled(helperBundleIdentifier as CFString, true)
NSLog("aktiviert")
} else {
SMLoginItemSetEnabled(helperBundleIdentifier as CFString, false)
NSLog("deaktiviert")
}
}
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
}
}
In the Launcher app in AppDelegate.swift:
//
// AppDelegate.swift
// LauncherApplication
//
// Created by Ralf Matz on 07.03.19.
// Copyright © 2019 Ralf Matz. All rights reserved.
//
import Cocoa
extension Notification.Name {
static let killLauncher = Notification.Name("killLauncher")
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@objc func terminate() {
NSApp.terminate(nil)
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
let mainAppIdentifier = "com.ralfmatz.onlyText"
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("MainApplication") //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
}
}
As recommended on other web sites I copied the executable app from the Library folder into the Applications folder so that the start oft the app at login can take effect.
Nevertheless when starting the app, enabling the launch at startup option, the app often does not show up after reboot. What went wrong?
Your help is greatly appreciated!
Best wishes,
Ralf