23.3 C
Canberra
Wednesday, February 25, 2026

launch a macOS app at login?


On this tutorial I will present you launch a very sandboxed macOS software on system startup written in Swift.

WARN: Replace: it’s best to merely add the LaunchAtLogin library to your challenge. It’ll care for the whole lot and it has another cool utility options.

Challenge setup

Let’s begin this tutorial by creating a brand new Xcode challenge with a macOS app template. Identify it for instance MainApplication, use storyboards and naturally choose Swift because the default language, we don’t want checks for this challenge in any respect.

Now that we’ve got the principle software goal, there’s this good little perform accessible referred to as SMLoginItemSetEnabled. With that perform you’ll be able to register an software bundle identifier to auto begin when the consumer logs in, however you can’t register your personal app identifier. Sounds loopy, huh? 😜

You possibly can register a bundle identifier embedded into your most important software to get auto-launched by the system. To do that you’ll have to create a brand new launcher software which might be launched later by your most important software.

You additionally must code signal your software along with your Developer ID, in any other case it received’t begin after you log in to macOS. Sandboxing is an important a part of the method, so just be sure you observe each instruction fastidiously.

Targets & configurations

Create a brand new goal inside your present challenge. Identify this new goal for instance LauncherApplication. Allow sandbox and code signing for each targets (most important and launcher apps) underneath the Signing & Capabilities tab. For the LauncherApplication goal within the construct settings set skip set up to sure.

launch a macOS app at login?

For the launcher app add a brand new entry to the Data.plist file: Software is background solely with the worth: sure. It will set your software as a background app, we don’t really want consumer interface for a launcher software, proper?

Background only

Add a brand new copy file construct section to your most important software goal to repeat your launcher software into the bundle. The vacation spot needs to be wrapper and the subpath needs to be Contents/Library/LoginItems.

Copy files

Hyperlink the ServiceManagement.framework to your most important software and double verify that the launcher app is embedded into your most important software.

Frameworks

From the LauncherApplication‘s storyboard file delete your window and your view controller, additionally you’ll be able to take away the ViewController.swift file from this goal. This can be a background app in any case, so we don’t want these silly issues to put round.

Creating the launcher programmatically

Someplace in your most important software it’s important to register your launcher software’s identifier. When your most important software begins it’s important to kill the launcher software if it’s nonetheless working. You are able to do this by sending a notification to that particular app with the NSDistributedNotificationCenter class.

import Cocoa
import ServiceManagement

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

@NSApplicationMain
class AppDelegate: NSObject {}


extension AppDelegate: NSApplicationDelegate {

    func applicationDidFinishLaunching(_ aNotification: Notification) {

        let launcherAppId = "com.tiborbodecs.LauncherApplication"
        let runningApps = NSWorkspace.shared.runningApplications
        let isRunning = !runningApps.filter { 
            $0.bundleIdentifier == launcherAppId 
        }.isEmpty

        SMLoginItemSetEnabled(launcherAppId as CFString, true)

        if isRunning {
            DistributedNotificationCenter.default().publish(
                identify: .killLauncher, 
                object: Bundle.most important.bundleIdentifier!
            )
        }
    }
}

Within the launcher software it’s important to begin your most important software if it’s not working already. That’s it. You also needs to subscribe for the notifications from the principle app to terminate if the launcher will not be wanted anymore.

import Cocoa

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

@NSApplicationMain
class AppDelegate: NSObject {

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

extension AppDelegate: NSApplicationDelegate {

    func applicationDidFinishLaunching(_ aNotification: Notification) {

        let mainAppIdentifier = "com.tiborbodecs.MainApplication"
        let runningApps = NSWorkspace.shared.runningApplications
        let isRunning = !runningApps.filter { 
            $0.bundleIdentifier == mainAppIdentifier 
        }.isEmpty

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

            let path = Bundle.most important.bundlePath as NSString
            var parts = path.pathComponents
            parts.removeLast()
            parts.removeLast()
            parts.removeLast()
            parts.append("MacOS")
            parts.append("MainApplication") //most important app identify

            let newPath = NSString.path(withComponents: parts)

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

That’s it, we’re able to launch. Export your most important software and right here is an important factor: code signal it along with your Developer ID. Begin it, shut it, sign off and again into the system. Hopefully your most important software might be working once more.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

[td_block_social_counter facebook="tagdiv" twitter="tagdivofficial" youtube="tagdiv" style="style8 td-social-boxed td-social-font-icons" tdc_css="eyJhbGwiOnsibWFyZ2luLWJvdHRvbSI6IjM4IiwiZGlzcGxheSI6IiJ9LCJwb3J0cmFpdCI6eyJtYXJnaW4tYm90dG9tIjoiMzAiLCJkaXNwbGF5IjoiIn0sInBvcnRyYWl0X21heF93aWR0aCI6MTAxOCwicG9ydHJhaXRfbWluX3dpZHRoIjo3Njh9" custom_title="Stay Connected" block_template_id="td_block_template_8" f_header_font_family="712" f_header_font_transform="uppercase" f_header_font_weight="500" f_header_font_size="17" border_color="#dd3333"]
- Advertisement -spot_img

Latest Articles