I spent about one day (maybe a little more) trying to add my application to the login element in the order in which it starts when macOS starts (user login).
So, following these steps, I did:
- Add a new project inside my main project, which I called Launcher
I use Automatic Signing (as the version of my Xcode) is different

In the section "Project Settings"> "Features" I switched to "Sandbox" in the "ON" position.
In the build phases, I added the following:

My launcher has Skip Install = YES

Launcher ( Swift, )
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSArray *pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents];
pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
NSString *path = [NSString pathWithComponents:pathComponents];
[[NSWorkspace sharedWorkspace] launchApplication:path];
[NSApp terminate:nil];
}
, ,
if(!SMLoginItemSetEnabled("click.remotely.Remotely-Click-Server-Launcher"
as CFString, Bool(checkboxButton.state as NSNumber) ) ) {
let alert: NSAlert = NSAlert()
alert.messageText = "Remotely.Click Server - Error";
alert.informativeText = "Application couldn't be added as
Login Item to macOS System Preferences > Users & Groups.";
alert.alertStyle = NSAlertStyle.warning;
alert.addButton(withTitle:"OK");
alert.runModal();
}
- , :

, , .
" Mac App Store Deployment" - , /Applications/, .
" ", " ", "MacOS App" , , .
"", (Launcher program). , , Launcher . ( ), ( ) . , , Launcher , Launcher . , /Applications/Main.app/Contents/Library/LoginItems/Launcher.app , Launcher Main () ( ).
, ?
,
kLSSharedFileListSessionLoginItems
, , - System Preferences this
.

!
Swift ( /, , Objective-C). - :
class LoginItemsList : NSObject {
let loginItemsList : LSSharedFileList = LSSharedFileListCreate(nil, kLSSharedFileListSessionLoginItems.takeRetainedValue(), nil).takeRetainedValue();
func addLoginItem(_ path: CFURL) -> Bool {
if(getLoginItem(path) != nil) {
print("Login Item has already been added to the list.");
return true;
}
var path : CFURL = CFURLCreateWithString(nil, "file:///Applications/Safari.app" as CFString, nil);
print("Path adding to Login Item list is: ", path);
if let loginItem = LSSharedFileListInsertItemURL(loginItemsList,
getLastLoginItemInList(),
nil, nil,
path,
nil, nil) {
print("Added login item is: ", loginItem);
return true;
}
return false;
}
func removeLoginItem(_ path: CFURL) -> Bool {
if let oldLoginItem = getLoginItem(path) {
print("Old login item is: ", oldLoginItem);
if(LSSharedFileListItemRemove(loginItemsList, oldLoginItem) == noErr) {
return true;
}
return false;
}
print("Login Item for given path not found in the list.");
return true;
}
func getLoginItem(_ path : CFURL) -> LSSharedFileListItem! {
var path : CFURL = CFURLCreateWithString(nil, "file:///Applications/Safari.app" as CFString, nil);
let loginItems : NSArray = LSSharedFileListCopySnapshot(loginItemsList, nil).takeRetainedValue();
var foundLoginItem : LSSharedFileListItem?;
var nextItemUrl : Unmanaged<CFURL>?;
print("App URL: ", path);
for var i in (0..<loginItems.count)
{
var nextLoginItem : LSSharedFileListItem = loginItems.object(at: i) as! LSSharedFileListItem;
if(LSSharedFileListItemResolve(nextLoginItem, 0, &nextItemUrl, nil) == noErr) {
print("Next login item URL: ", nextItemUrl!.takeUnretainedValue());
if(nextItemUrl!.takeRetainedValue() == path) {
foundLoginItem = nextLoginItem;
}
}
}
return foundLoginItem;
}
func getLastLoginItemInList() -> LSSharedFileListItem! {
let loginItems : NSArray = LSSharedFileListCopySnapshot(loginItemsList, nil).takeRetainedValue() as NSArray;
if(loginItems.count > 0) {
let lastLoginItem = loginItems.lastObject as! LSSharedFileListItem;
print("Last login item is: ", lastLoginItem);
return lastLoginItem
}
return kLSSharedFileListItemBeforeFirst.takeRetainedValue();
}
func isLoginItemInList(_ path : CFURL) -> Bool {
if(getLoginItem(path) != nil) {
return true;
}
return false;
}
static func appPath() -> CFURL {
return NSURL.fileURL(withPath: Bundle.main.bundlePath) as CFURL;
}
}
, / ,
let loginItemsList = LoginItemsList();
if( checkboxButton.state == 0) {
if(!loginItemsList.removeLoginItem(LoginItemsList.appPath())) {
print("Error while removing Login Item from the list.");
}
} else {
if(!loginItemsList.addLoginItem(LoginItemsList.appPath())) {
print("Error while adding Login Item to the list.");
}
}
( Xcode Play) /Applications, , .
. , Inserting Login Item nil.

, ( stackoverflow) Objective-C ( Unix < > Swift)
.m .h Bridging-Header.h, :
- (void)enableLoginItemWithURL:(NSURL *)itemURL
{
LSSharedFileListRef loginListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
if (loginListRef) {
LSSharedFileListItemRef loginItemRef = LSSharedFileListInsertItemURL(loginListRef,
kLSSharedFileListItemLast,
NULL,
NULL,
(__bridge CFURLRef) itemURL,
NULL,
NULL);
if (loginItemRef) {
CFRelease(loginItemRef);
}
CFRelease(loginListRef);
}
}
( ) - .
, LSSharedFileListInsertItemURL nil, > > .
, , ?
1
, ( Launcher ) iMac (MacOS Sierra XCode 8.3), , , , , , - Xcode ( , - ) MacBook Air, , OS X El Capitan 10.11.5 Xcode 8.0.
, :
https://youtu.be/6fnLzkh5Rbs
https://www.youtube.com/watch?v=sUE7Estju0U
iMac, nil LSSharedFileListInsertItemURL. , .
, :
https://youtu.be/S_7ctQLkIuA
2
MacOS Sierra 10.12.5 El Capitan 10.11.5 Xcode 8.3.2 Xcode 8.0.0 > >
! LSSharedFileListInsertItemURL Sandboxing ! :
https://youtu.be/UvDkby0t_WI