Replace: you must merely add the LaunchAtLogin library to your venture. It will deal with all the things and it has another cool utility options.
Venture setup
Let’s begin this tutorial by creating a brand new Xcode venture with a macOS app template. Title it for instance MainApplication, use storyboards and naturally choose Swift because the default language, we do not want assessments for this venture in any respect.
Now that now we have the principle software goal, there may be this good little perform accessible referred to as SMLoginItemSetEnabled. With that perform you may register an software bundle identifier to auto begin when the consumer logs in, however you can’t register your individual app identifier. Sounds loopy, huh? 😜
You’ll be able to 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 can 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 will not begin after you log in to macOS. Sandboxing is an important a part of the method, so just be sure you comply with each instruction rigorously.
Targets & configurations
Create a brand new goal inside your present venture. Title this new goal for instance LauncherApplication. Allow sandbox and code signing for each targets (most important and launcher apps) beneath the Signing & Capabilities tab. For the LauncherApplication goal within the construct settings set skip set up to sure.
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 do not really want consumer interface for a launcher software, proper?
Add a brand new copy file construct part 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.
Hyperlink the ServiceManagement.framework to your most important software and double verify that the launcher app is embedded into your most important software.
From the LauncherApplication‘s storyboard file delete your window and your view controller, additionally you may take away the ViewController.swift file from this goal. It is a background app in spite of everything, so we do not want these silly issues to put round.
Creating the launcher programmatically
Someplace in your most important software it’s a must to register your launcher software’s identifier. When your most important software begins it’s a must to kill the launcher software 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.Title {
static let killLauncher = Notification.Title("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().put up(
title: .killLauncher,
object: Bundle.most important.bundleIdentifier!
)
}
}
}
Within the launcher software it’s a must to begin your most important software if it is not operating already. That is it. You also needs to subscribe for the notifications from the principle app to terminate if the launcher just isn’t wanted anymore.
import Cocoa
extension Notification.Title {
static let killLauncher = Notification.Title("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.most important.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 most important software and right here is crucial factor: code signal it along with your Developer ID. Begin it, shut it, log off and again into the system. Hopefully your most important software can be operating once more.
