Как да накарате приложението ви да се отваря при влизане?

Просто се чудя как мога да направя така, че приложението ми да се отваря автоматично при влизане, но това да може да се включва и изключва чрез квадратче за отметка в прозореца с предпочитания.


person Joshua    schedule 02.05.2009    source източник
comment
Към коя система се насочвате? Различно е в зависимост дали искате 10.5, 10.4 или преди 10.4   -  person Jason Coco    schedule 02.05.2009


Отговори (4)


Има прилично описание на това какво да правите в CocoaDev.

По принцип ще искате да използвате API в LaunchServices/LSSharedFileList.h, ако можете да се насочите към Mac OS X 10.5 или по-нова версия. Преди 10.5 нямаше чист API, така че трябва ръчно да манипулирате елементите за влизане (Примерен код във връзката за разработчициg).

Ето примерен код (мъртъв) за Leopard, който споменах в коментарите. Намерено чрез тази публикация в блог. Кодът, от който се нуждаете, за да активирате или деактивирате стартирането при влизане, е в Controller.m.

person Naaff    schedule 02.05.2009
comment
Съжалявам, но това не изглежда да го обяснява. - person Joshua; 02.05.2009
comment
Това е много старо, използвам леопард. Все още ли работи? - person Joshua; 02.05.2009
comment
Това, което трябва да използвате, е API LaunchServices/LSSharedFileList.h. Вижте secondgear-public.googlecode.com/svn/trunk/SGLaunchAtLogin за някакъв примерен код. Кодът, от който се нуждаете, е в Controller.m - person Naaff; 02.05.2009
comment
Вече не можете да използвате методите LSSharedFileList.h за приложения в пясъчна среда в Mac App Store: developer.apple.com/library/mac/#documentation/Security/ - person pkamb; 28.09.2012
comment
Да, не работи с SandBoxed приложения, които вече са задължителни в Mac Appstore... Има ли промяна??? Благодаря !! - person Regis_AG; 09.01.2013

Ето някакъв код, който използвам, базиран е на изходния код на Growl.

+ (BOOL) willStartAtLogin:(NSURL *)itemURL
{
    Boolean foundIt=false;
    LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
    if (loginItems) {
        UInt32 seed = 0U;
        NSArray *currentLoginItems = [NSMakeCollectable(LSSharedFileListCopySnapshot(loginItems, &seed)) autorelease];
        for (id itemObject in currentLoginItems) {
            LSSharedFileListItemRef item = (LSSharedFileListItemRef)itemObject;

            UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
            CFURLRef URL = NULL;
            OSStatus err = LSSharedFileListItemResolve(item, resolutionFlags, &URL, /*outRef*/ NULL);
            if (err == noErr) {
                foundIt = CFEqual(URL, itemURL);
                CFRelease(URL);

                if (foundIt)
                    break;
            }
        }
        CFRelease(loginItems);
    }
    return (BOOL)foundIt;
}

+ (void) setStartAtLogin:(NSURL *)itemURL enabled:(BOOL)enabled
{
    OSStatus status;
    LSSharedFileListItemRef existingItem = NULL;

    LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
    if (loginItems) {
        UInt32 seed = 0U;
        NSArray *currentLoginItems = [NSMakeCollectable(LSSharedFileListCopySnapshot(loginItems, &seed)) autorelease];
        for (id itemObject in currentLoginItems) {
            LSSharedFileListItemRef item = (LSSharedFileListItemRef)itemObject;

            UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
            CFURLRef URL = NULL;
            OSStatus err = LSSharedFileListItemResolve(item, resolutionFlags, &URL, /*outRef*/ NULL);
            if (err == noErr) {
                Boolean foundIt = CFEqual(URL, itemURL);
                CFRelease(URL);

                if (foundIt) {
                    existingItem = item;
                    break;
                }
            }
        }

        if (enabled && (existingItem == NULL)) {
            LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst,
                                          NULL, NULL, (CFURLRef)itemURL, NULL, NULL);

        } else if (!enabled && (existingItem != NULL))
            LSSharedFileListItemRemove(loginItems, existingItem);

        CFRelease(loginItems);
    }       
}

Ако искате лесно за внедряване квадратче за отметка, направете @property BOOL startAtLogin; в един от вашите класове и го внедрите по следния начин. Просто свържете стойността на квадратчето за отметка към свойството и всичко трябва да работи безпроблемно.

- (NSURL *)appURL
{
    return [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
}

- (BOOL)startAtLogin
{
    return [LoginItem willStartAtLogin:[self appURL]];
}

- (void)setStartAtLogin:(BOOL)enabled
{
    [self willChangeValueForKey:@"startAtLogin"];
    [LoginItem setStartAtLogin:[self appURL] enabled:enabled];
    [self didChangeValueForKey:@"startAtLogin"];
}
person Nick Moore    schedule 23.02.2010
comment
Този пример, подобно на повечето подобни съществуващи, не се занимава със случая, когато приложението е изтрито и след това е инсталирано отново на друго място, след като е било добавено към елементите за влизане - защото след това ще добави друг запис, без да премахва мъртвия. За да направите това правилно, преди да добавите ново, първо трябва да прегледате всички записи и да премахнете всички, чиито имена започват с името на приложението. - person Thomas Tempelmann; 08.08.2016
comment
Добра точка @ThomasTempelmann. Но защо записи започващи с името на приложението, а не точно съвпадение? - person Nick Moore; 29.08.2016
comment
Ник, търсенето на точното име не е добро, защото дори ако разархивирате приложение само два пъти, вече получавате добавено -2 и потребителите може да започнат това. Потребителите също може да са склонни да преименуват вашето приложение (все пак не сме на Windows). Обикновено името ще бъде добавено към. Но ако името на приложението ви е достатъчно уникално, потърсете своя компонент на последния път навсякъде в елементите за влизане. Или дори да локализирате всеки един и да проверите идентификационните им номера на пакета - това е още по-сигурно. Само имайте предвид, че някои връзки може да са мъртви. - person Thomas Tempelmann; 29.08.2016
comment
Съгласен съм, че проверката на всеки идентификатор на пакет ще бъде най-добрият вариант. Или най-малкото (ако скоростта на проверка на всеки идентификатор се окаже проблем), проверете идентификатора на пакета, след като съвпаднете с частичното име - за да сте сигурни, че не премахваме записа за несвързано приложение с подобно име. - person Nick Moore; 30.08.2016
comment
Работи ли с новите OS версии high sierra и Mojave - person Durgaprasad; 31.07.2018
comment
Потвърдете, че това спря да работи в Mojave - person Marek H; 06.01.2020

Извикайте метода, поставен по-долу, с URL адрес на файл, сочещ към вашето приложение, за да го добавите към елементите за влизане на текущия потребител.

За да деактивирате отново, ще трябва да получите същия loginListRef, да го преобразувате в масив и да преминете през него, докато намерите елемента с URL адреса, който искате да деактивирате. Накрая извикайте LSSaredFileListItemRemove със съответните аргументи.

Късмет :)

- (void)enableLoginItemWithURL:(NSURL *)itemURL
{
    LSSharedFileListRef loginListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);

    if (loginListRef) {
        // Insert the item at the bottom of Login Items list.
        LSSharedFileListItemRef loginItemRef = LSSharedFileListInsertItemURL(loginListRef, 
                                             kLSSharedFileListItemLast, 
                                             NULL, 
                                             NULL,
                                             (CFURLRef)itemURL, 
                                             NULL, 
                                             NULL);     
        if (loginItemRef) {
            CFRelease(loginItemRef);
        }
        CFRelease(loginListRef);
    }
}
person Dirk Stoop    schedule 02.05.2009
comment
С какво да заменя това: // Вмъкнете елемента в долната част на списъка с елементи за влизане. ? И как бих могъл да получа същия loginListRef, да го конвертирам в масив и да го обикалям, докато не намеря елемента с URL адреса, който искате да деактивирате? - person Joshua; 02.05.2009
comment
Или просто го накарайте да превключва с квадратче за отметка, как да направя това? - person Joshua; 02.05.2009
comment
Здравей, Джошуа, има доста неща за покриване. Кодът, който публикувах, трябва да ви помогне да разберете как да добавите нещо към елементите за влизане. Всъщност свързването на това с квадратче за отметка би трябвало да е тривиално, ако вече ви е малко удобно да работите по проект за какао. Ако не сте, бих препоръчал да започнете от тук: tinyurl.com/3z4r9b - person Dirk Stoop; 03.05.2009
comment
Как да премахна от списъка за влизане? - person maxisme; 22.09.2015
comment
за съжаление този код е остарял на 10.11 - person Duck; 18.07.2017

Вижте също SO въпрос: Регистриране като елемент за влизане с какао

person Nathan Kinsinger    schedule 02.05.2009