Зарегистрироваться в какао как элемент входа? - PullRequest
24 голосов
/ 04 марта 2009

Google дал мне: http://developer.apple.com/samplecode/LoginItemsAE/index.html

И я подумал, что должен быть лучший способ, чем использование AppleScript Events.

Итак, я скачал источники Growl. Они используют точные источники из этой статьи разработчика Apple.

Есть ли лучший способ?

(Я имею в виду элементы входа в учетные записи в системных настройках, т. Е. Запуск моей программы при входе пользователя программным способом)

Ответы [ 7 ]

27 голосов
/ 04 марта 2009

В Leopard есть новый API под названием LSSharedFileList. Одна из вещей, которую он позволяет вам делать, это просматривать и редактировать список элементов входа (называемых элементами входа в сеанс в этом API).

Кстати, я ведущий разработчик Growl. Мы еще не отказались от AE, потому что нам все еще нужен Tiger, но я думаю о том, чтобы сбросить его до 1.2 (пока не обсуждал это с другими разработчиками). Когда мы удаляем Tiger, мы также удаляем LoginItemsAE и переключаемся на API Списка общих файлов.


РЕДАКТИРОВАТЬ с 2012 года: с 2009 года, когда я первоначально написал этот ответ, Growl перешел на LSSharedFileList, и я покинул проект.

14 голосов
/ 25 января 2011

Я наткнулся на LaunchAtLoginController Бена Кларка-Робинсона . Очень элегантное решение очень распространенной проблемы.

10 голосов
/ 30 ноября 2013

Это работает на xcode 5.

- (BOOL)isLaunchAtStartup {
    // See if the app is currently in LoginItems.
    LSSharedFileListItemRef itemRef = [self itemRefInLoginItems];
    // Store away that boolean.
    BOOL isInList = itemRef != nil;
    // Release the reference if it exists.
    if (itemRef != nil) CFRelease(itemRef);

    return isInList;
}

- (void)toggleLaunchAtStartup {
    // Toggle the state.
    BOOL shouldBeToggled = ![self isLaunchAtStartup];
    // Get the LoginItems list.
    LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
    if (loginItemsRef == nil) return;
    if (shouldBeToggled) {
        // Add the app to the LoginItems list.
        CFURLRef appUrl = (__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
        LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL);
        if (itemRef) CFRelease(itemRef);
    }
    else {
        // Remove the app from the LoginItems list.
        LSSharedFileListItemRef itemRef = [self itemRefInLoginItems];
        LSSharedFileListItemRemove(loginItemsRef,itemRef);
        if (itemRef != nil) CFRelease(itemRef);
    }
    CFRelease(loginItemsRef);
}

- (LSSharedFileListItemRef)itemRefInLoginItems {
    LSSharedFileListItemRef res = nil;

    // Get the app's URL.
    NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
    // Get the LoginItems list.
    LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
    if (loginItemsRef == nil) return nil;
    // Iterate over the LoginItems.
    NSArray *loginItems = (__bridge NSArray *)LSSharedFileListCopySnapshot(loginItemsRef, nil);
    for (id item in loginItems) {
        LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)(item);
        CFURLRef itemURLRef;
        if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) {
            // Again, use toll-free bridging.
            NSURL *itemURL = (__bridge NSURL *)itemURLRef;
            if ([itemURL isEqual:bundleURL]) {
                res = itemRef;
                break;
            }
        }
    }
    // Retain the LoginItem reference.
    if (res != nil) CFRetain(res);
    CFRelease(loginItemsRef);
    CFRelease((__bridge CFTypeRef)(loginItems));

    return res;
}
4 голосов
/ 04 марта 2009

Я делаю это в приложении, которое пишу :

Проверьте UKLoginItemRegistry для простого способа сделать это прагматично. Афайк, в Tiger нет способа сделать это без Apple Events; в Leopard есть лучший способ, но если вы используете UKLoginItemRegistry, это действительно не проблема. Вот полный код для реализации пункта меню «Открыть при входе в систему» ​​

+ (bool)isAppSetToRunAtLogon {
  int ret = [UKLoginItemRegistry indexForLoginItemWithPath:[[NSBundle mainBundle] bundlePath]];
  NSLog(@"login item index = %i", ret);
  return (ret >= 0);
}

- (IBAction)toggleOpenAtLogon:(id)sender {
  if ([PopupController isAppSetToRunAtLogon]) {
    [UKLoginItemRegistry removeLoginItemWithPath:[[NSBundle mainBundle] bundlePath]];
  } else {
    [UKLoginItemRegistry addLoginItemWithPath:[[NSBundle mainBundle] bundlePath] hideIt: NO];
  }
}
3 голосов
/ 15 сентября 2014

Я реорганизовал некоторые ответы здесь, чтобы предоставить категорию на NSApplication, которая предоставляет свойство launchAtLogin.

https://gist.github.com/joerick/73670eba228c177bceb3

2 голосов
/ 03 июля 2018

SMLoginItemSetEnabled - еще один современный вариант, см. Современные элементы входа в систему статья Кори Бохона, где он объясняет, что вам нужно создать вспомогательное приложение, единственная цель которого - запустить основное приложение. Также есть полное пошаговое объяснение в SMLoginItemSetEnabled - начать при входе в систему с изолированной программной оболочкой приложения при переполнении стека.

0 голосов
/ 06 декабря 2012

Посмотрите на пример с открытым исходным кодом: https://github.com/invariant/rhpnotifier (LoginItem.m, LoginItem.h)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...