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() -> Bool { return (itemReferencesInLoginItems().existingReference != nil) } func itemReferencesInLoginItems() -> (existingReference: LSSharedFileListItemRef?, lastReference: LSSharedFileListItemRef?) { if let appUrl : NSURL = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath) { let loginItemsRef = LSSharedFileListCreate(nil, kLSSharedFileListSessionLoginItems.takeRetainedValue(), nil).takeRetainedValue() as LSSharedFileListRef? if loginItemsRef != nil { let loginItems: NSArray = LSSharedFileListCopySnapshot(loginItemsRef, nil).takeRetainedValue() as NSArray if(loginItems.count > 0) { let lastItemRef: LSSharedFileListItemRef = loginItems.lastObject as! LSSharedFileListItemRef for var i = 0; i < loginItems.count; ++i { let currentItemRef: LSSharedFileListItemRef = loginItems.objectAtIndex(i) as! LSSharedFileListItemRef if let itemURL = LSSharedFileListItemCopyResolvedURL(currentItemRef, 0, nil) { if (itemURL.takeRetainedValue() as NSURL).isEqual(appUrl) { return (currentItemRef, lastItemRef) } } } return (nil, lastItemRef) } else { let addatstart: LSSharedFileListItemRef = kLSSharedFileListItemBeforeFirst.takeRetainedValue() return(nil,addatstart) } } } return (nil, nil) } func toggleLaunchAtStartup() { let itemReferences = itemReferencesInLoginItems() let shouldBeToggled = (itemReferences.existingReference == nil) if let loginItemsRef = LSSharedFileListCreate( nil, kLSSharedFileListSessionLoginItems.takeRetainedValue(), nil).takeRetainedValue() as LSSharedFileListRef? { if shouldBeToggled { if let appUrl : CFURLRef = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath) { LSSharedFileListInsertItemURL(loginItemsRef, itemReferences.lastReference, nil, nil, appUrl, nil, nil) } } else { if let itemRef = itemReferences.existingReference { LSSharedFileListItemRemove(loginItemsRef,itemRef); } } } }
But LSSharedFileListCreate
, LSSharedFileListInsertItemURL
, LSSharedFileListItemRemove
, kLSSharedFileListItemBeforeFirst
, LSSharedFileListItemCopyResolvedURL
, LSSharedFileListCopySnapshot
, kLSSharedFileListSessionLoginItems
were deprecated in OS X 10.11. How to make this work on latest version of Mac OS? How to change or rewrite this code?
Right-click on the app and hover over Options in the menu. Apps that are set to open automatically will have a check mark next to Open at Login. Click that option to uncheck it and disable it from opening.
Temporarily prevent items from opening automatically when you log in. If you see the login window, press and hold the Shift key while you click the Log In button, then release the Shift key when the Dock opens.
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With