Обработка событий щелчка с помощью NSUserNotification, отправленного из приложения CLI

Я создал приложение командной строки OSX в Objective C, и теперь оно запускает события уведомлений боковой панели, например:

NSUserNotification *n = [[NSUserNotification alloc] init];
n.title = @"My Title";
n.subtitle = @"my subtitle";
n.informativeText = @"some informative text";
[NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:n];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];

Я даже использовал эту технику, чтобы использовать значок другого приложения вместо черного значка терминала.

Проблема, однако, заключается в том, что когда вы щелкаете элемент, он запускает приложение командной строки вместо того приложения, которое мне нужно. Как я могу сделать так, чтобы щелчок по уведомлению на боковой панели запускал мое отдельное приложение с графическим интерфейсом?

EDIT: возможно, мне нужно использовать AppleScript, чтобы сообщить моему приложению CLI, чтобы оно вызывало мое приложение с графическим интерфейсом и давало ему указание отправить уведомление? Таким образом, делегат события устанавливается для приложения с графическим интерфейсом, а не для приложения CLI. Если это так, я не знаю, как запустить AppleScript и передать сообщение моему приложению с графическим интерфейсом, а также как приложение с графическим интерфейсом может прочитать это сообщение.


person Volomike    schedule 16.04.2016    source источник


Ответы (1)


Решение состоит в том, что вы не делаете это таким образом. Если у вас есть приложение CLI, которому необходимо опубликовать уведомление на боковой панели для пользователя, и когда пользователь щелкает его, оно открывает приложение-компаньон с графическим интерфейсом, то есть два способа справиться с этим:

• Сделайте ваше приложение с графическим интерфейсом доступным для сценариев, чтобы оно могло получать сообщения AppleScript от вашего приложения CLI и действовать в соответствии с ними (например, отправлять уведомление на боковой панели). Это объясняется здесь. Это самая элегантная техника.

• Или вы можете следовать следующему примеру, чтобы создать приложение Cocoa без графического интерфейса, которое выступает в качестве посредника между приложением CLI и приложением-компаньоном с графическим интерфейсом.

Промежуточный метод приложения Cocoa без графического интерфейса

1. Создайте так называемое приложение Cocoa без графического интерфейса пользователя, которое будет действовать как посредник между вашим приложением CLI и приложением с графическим интерфейсом. Это устраняет открытие уродливого окна терминала, если вы создали приложение CLI. Шаги:

а. Создайте новое приложение Cocoa по умолчанию.

б. Удалите запись NSMainNibFile из Info.plist.

в. Удалите файл XIB и материал AppDelegate по умолчанию (.m, .h).

д. Закомментируйте вызов NSApplicationMain в файле main.m в функции main().

е. Добавьте ключ LSUIElement в свой Info.plist и установите для него значение YES.

2. Установите значок для этого приложения без графического интерфейса, скопировав файл AppIcon.icns из скомпилированного приложения с графическим интерфейсом в это приложение без графического интерфейса в том же каталоге, где находится файл main.m. Затем в вашем Info.plist приложения без графического интерфейса установите для CFBundleIconFile значение просто AppIcon. Затем выполните очистку вашего проекта, чтобы он использовал этот новый значок. Примечание. XCode может вести себя странно, когда значок не отображается должным образом, но когда вы просматриваете его в Finder, все будет в порядке.

3. Установите для main.m приложения Cocoa без графического интерфейса следующее:

#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[]) {


    NSString *sTitle = @"";
    NSString *sSubTitle = @"";
    NSString *sText = @"";
    try {
        sTitle = @(argv[1]);
        sSubTitle = @(argv[2]);
        sText = @(argv[3]);
    } catch (...) {
    }

    if ([sTitle isEqualToString:@""]) {
        NSString *script = @"tell app \"";
        // change me to your real GUI application path
        script = [script stringByAppendingString:@"/Applications/Example.app"];
        script = [script stringByAppendingString:@"\" to activate"];
        NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:script];
        [appleScript executeAndReturnError:nil];
        exit(0);
    }

    
    NSUserNotification *n = [[NSUserNotification alloc] init];
    n.title = sTitle;
    if (![sSubTitle isEqualToString:@""]) {
        n.subtitle = sSubTitle;
    }
    n.informativeText = sText;
    [NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:n];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
    return 0;

}

4. Скомпилируйте это приложение и вставьте папку этого приложения в папку /Applications/Example.app/Contents/Resources (конечно, измените это).

5. Теперь вы можете использовать следующий код из своего приложения CLI для отправки уведомления и использовать значок, используемый в вашем приложении с графическим интерфейсом, что очень приятно. Когда пользователь нажимает на уведомление, он открывает ваше приложение с графическим интерфейсом вместо приложения без графического интерфейса. (На самом деле, когда вы щелкаете уведомление на боковой панели, оно открывает приложение без графического интерфейса, но оно не видно. Приложение без графического интерфейса не видит, что ему передаются никакие параметры, поэтому оно не показывает другое уведомление. Вместо этого оно знает, что нужно запустите приложение с графическим интерфейсом через AppleScript.)

#include <string>

std::string sTitle = "Sample Title";
std::string sSubTitle = "sample subtitle";
std::string sText = "some text";
std::string sCmd = "open -a \"";
// change me to the path of your GUI application
sCmd += "/Applications/Example.app";
// change notify.app to the name of your GUI-less application
sCmd += "/Contents/Resources/notify.app";
sCmd += "\" --args ";
sCmd += "\"" + sTitle + "\" ";
sCmd += "\"" + sSubTitle + "\" ";
sCmd += "\"" + sText + "\"";
system(sCmd.c_str());
person Volomike    schedule 16.04.2016