I need to write a function that adds my application to Startup items on OS X 10.11. That\'s what I found at the moment:
func applicationIsInStartUpItems() ->
In Swift 3.0 it looks like this:
In your main application AppDelegate:
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Check if the launcher app is started
var startedAtLogin = false
for app in NSWorkspace.shared().runningApplications {
if app.bundleIdentifier == NCConstants.launcherApplicationIdentifier {
startedAtLogin = true
}
}
// If the app's started, post to the notification center to kill the launcher app
if startedAtLogin {
DistributedNotificationCenter.default().postNotificationName(NCConstants.KILLME, object: Bundle.main.bundleIdentifier, userInfo: nil, options: DistributedNotificationCenter.Options.deliverImmediately)
}
}
In the Launcher application AppDelegate:
func applicationDidFinishLaunching(_ aNotification: Notification) {
let mainAppIdentifier = "<main-app-bundle-id>"
let running = NSWorkspace.shared().runningApplications
var alreadyRunning = false
// loop through running apps - check if the Main application is running
for app in running {
if app.bundleIdentifier == mainAppIdentifier {
alreadyRunning = true
break
}
}
if !alreadyRunning {
// Register for the notification killme
DistributedNotificationCenter.default().addObserver(self, selector: #selector(self.terminate), name: NCConstants.KILLME, object: mainAppIdentifier)
// Get the path of the current app and navigate through them to find the Main Application
let path = Bundle.main.bundlePath as NSString
var components = path.pathComponents
components.removeLast(3)
components.append("MacOS")
components.append("<your-app-name>")
let newPath = NSString.path(withComponents: components)
// Launch the Main application
NSWorkspace.shared().launchApplication(newPath)
}
else {
// Main application is already running
self.terminate()
}
}
func terminate() {
print("Terminate application")
NSApp.terminate(nil)
}
Eventually, in the main application I added a user interface with a toggle button. The user can choose to launch the app at login or not. The choice is stored into the UserDefaults. In the View Controller:
@IBAction func toggleLaunchAtLogin(_ sender: Any) {
if toggleOpenAppLogin.selectedSegment == 0 {
if !SMLoginItemSetEnabled(NCConstants.launcherApplicationIdentifier as CFString, true) {
print("The login item was not successfull")
toggleOpenAppLogin.setSelected(true, forSegment: 1)
}
else {
UserDefaults.standard.set("true", forKey: "appLoginStart")
}
}
else {
if !SMLoginItemSetEnabled(NCConstants.launcherApplicationIdentifier as CFString, false) {
print("The login item was not successfull")
toggleOpenAppLogin.setSelected(true, forSegment: 0)
}
else {
UserDefaults.standard.set("false", forKey: "appLoginStart")
}
}
}
I hope this can help somebody.
You have to use the Service Management framework now. You create a helper application that you add to your application bundle and its job is to run code to launch your main application. Some resources for you: