App doesn't start at Login

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

Replies

Your first link seems to accurate describe how to create a menubar app. However, it links to other sites that incorrectly describe how to launch an app at login. If you ever find yourself on a GitHub page and the files say "last modified: 9 years ago", find another GitHub page.


Your second link does have the correct information about how to build a service management login item. Use these instructions.


I don't know what those "other web sites" are saying. I can definitely tell you that copying somethe from the Library folder into the Applications folder is not going to do anything to launch an app at login. I suggest you ignore those "other web sites".

Thank you, John Daniel