Tuesday, July 4, 2023
HomeiOS DevelopmentHow one can launch a macOS app at login?

How one can launch a macOS app at login?


Replace: it’s best to merely add the LaunchAtLogin library to your challenge. It’s going to care for all the things and it has another cool utility options.

Undertaking 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 do not want exams for this challenge in any respect.

Now that now we have the principle utility goal, there may be this good little operate out there known as SMLoginItemSetEnabled. With that operate you possibly can register an utility bundle identifier to auto begin when the person logs in, however you cannot register your personal app identifier. Sounds loopy, huh? 😜

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

You additionally need to code signal your utility together with your Developer ID, in any other case it will not begin after you log in to macOS. Sandboxing is a vital a part of the method, so just be sure you comply with 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 (fundamental and launcher apps) underneath the Signing & Capabilities tab. For the LauncherApplication goal within the construct settings set skip set up to sure.

Skip install

For the launcher app add a brand new entry to the Information.plist file: Software is background solely with the worth: sure. It will set your utility as a background app, we do not actually need person interface for a launcher software, proper?

Background only

Add a brand new copy file construct part to your fundamental utility goal to repeat your launcher utility into the bundle. The vacation spot ought to be wrapper and the subpath ought to be Contents/Library/LoginItems.

Copy files

Hyperlink the ServiceManagement.framework to your fundamental utility and double examine that the launcher app is embedded into your fundamental utility.

Frameworks

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

Creating the launcher programmatically

Someplace in your fundamental utility it’s a must to register your launcher utility’s identifier. When your fundamental utility begins it’s a must to kill the launcher utility if it is nonetheless operating. 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().submit(
                title: .killLauncher, 
                object: Bundle.fundamental.bundleIdentifier!
            )
        }
    }
}

Within the launcher utility it’s a must to begin your fundamental utility if it isn’t operating already. That is 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), 
                title: .killLauncher, 
                object: mainAppIdentifier
            )

            let path = Bundle.fundamental.bundlePath as NSString
            var parts = path.pathComponents
            parts.removeLast()
            parts.removeLast()
            parts.removeLast()
            parts.append("MacOS")
            parts.append("MainApplication") 

            let newPath = NSString.path(withComponents: parts)

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

That is it, we’re able to launch. Export your fundamental utility and right here is a very powerful factor: code signal it together with your Developer ID. Begin it, shut it, sign off and again into the system. Hopefully your fundamental utility might be operating once more.



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments