如何让程序在登录时自动启动?

Fre*_*ddy 9 macos cocoa objective-c

如何设置菜单栏应用程序以在登录时自动启动?我希望这是默认的.我可以通过在info.plist中添加一个bool来做到这一点吗?

Căt*_*tan 14

(此解决方案仅适用于非沙盒应用程序.LSSharedFile此解决方案中使用的功能仅适用于非沙盒应用程序.)

您使用会话登录项共享文件列表.当您在配置文件设置下检查登录项时,这是"系统偏好设置"中显示的列表.

应用程序中的典型场景是在应用程序的首选项中提供一个复选框,允许用户选择是否要在启动应用程序时启动应用程序.如果您打算通过应用程序商店分发,请不要将应用程序设置为默认登录时启动.你会被拒绝:)

因此,在这种情况下,我们将在App Delegate中创建一个名为"launchOnLogin"的属性,我们将复选框的值绑定到此属性.

getter方法将检查我们的app的bundle id是否在共享列表中并返回true或false.

setter方法在共享列表中广告或删除项目.

开始:

AppDelegate.h

@property (atomic, assign) BOOL launchOnLogin;
Run Code Online (Sandbox Code Playgroud)

AppDelegate.m

- (BOOL)launchOnLogin 
{
    LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
    CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL);
    NSArray* loginItems = [NSMakeCollectable(snapshotRef) autorelease];
    NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
    for (id item in loginItems) {
        LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item;
        CFURLRef itemURLRef;
        if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) {
            NSURL *itemURL = (NSURL *)[NSMakeCollectable(itemURLRef) autorelease];
            if ([itemURL isEqual:bundleURL]) {
                return YES;
            }
        }
    }
    return NO;
}

- (void)setLaunchOnLogin:(BOOL)launchOnLogin
{    
    NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
    LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);

    if (launchOnLogin) {
        NSDictionary *properties;
        properties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"com.apple.loginitem.HideOnLaunch"];
        LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsListRef, kLSSharedFileListItemLast, NULL, NULL, (CFURLRef)bundleURL, (CFDictionaryRef)properties,NULL);
        if (itemRef) {
            CFRelease(itemRef);
        }
    } else {
        LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
        CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL);
        NSArray* loginItems = [NSMakeCollectable(snapshotRef) autorelease];

        for (id item in loginItems) {
            LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item;
            CFURLRef itemURLRef;            
            if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) {
                NSURL *itemURL = (NSURL *)[NSMakeCollectable(itemURLRef) autorelease];
                if ([itemURL isEqual:bundleURL]) {
                    LSSharedFileListItemRemove(loginItemsListRef, itemRef);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是它.现在,如果您正确地执行绑定和所有操作,您将看到您的应用程序如何实时显示并从"系统首选项"列表中消失.

实际上在登录时启动应用程序的部分

// Get the path of the app
NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];

// Get the list you want to add the path to
LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);

// Set the app to be hidden on launch
NSDictionary *properties = @{@"com.apple.loginitem.HideOnLaunch": @YES};

// Add the item to the list
LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsListRef, kLSSharedFileListItemLast, NULL, NULL, (CFURLRef)bundleURL, (CFDictionaryRef)properties,NULL);
Run Code Online (Sandbox Code Playgroud)

请注意,上面的代码是保留/释放,但如果需要,将它转换为ARC非常简单.

希望这可以帮助.

  • @ManiaChamp,我假设你的应用程序是沙盒.如果是这样,所有LSSharedFile函数都不起作用.请参阅https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/DesigningYourSandbox/DesigningYourSandbox.html#//apple_ref/doc/uid/,查看"为您的应用创建登录项" TP40011183-CH4-SW3. (3认同)