OSX: как найти имя файла, запустившего ваше приложение
Задавая информацию о файле, вы можете связать приложение с определенным типом файла, чтобы при нажатии приложение запускалось. Мой вопрос заключается в том, как приложение может обнаружить полное имя файла, вызвавшего его запуск. В Windows это невероятно просто, поскольку windows передает имя файла в качестве параметра командной строки. У меня вопрос, как сделать то же самое под OSX.
1 ответ
Приложения Mac не запускаются каждый раз, когда открывается связанный файл. Они могут быть запущены, но если они уже запущены, то их просто просят открыть другой файл. Таким образом, путь не приходит к приложению через командную строку. Он отправляется как сообщение приложению, которому для его получения необходимо обработать цикл выполнения (NSRunLoop).
В обычной программе Какао вы реализуете NSApplicationDelegate и реализуете метод (в именовании ObjC):
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
Если вы поддерживаете только 10.13+, предпочтительный метод был изменен на:
- (void)application:(NSApplication *)application openURLs:(NSArray<NSURL *> *)urls;
ОС будет вызывать это, когда вашему приложению нужно открыть файл, если для его принятия запущен объект NSApplication. Обычно вы создаете объект NSApplication, вызывая NSApplicationMain()
, но вы можете реализовать свою собственную версию NSApplicationMain()
если вам нужно (см. документацию NSApplication для деталей).
Можно ответить на эти открытые запросы без NSApplication или любого Objective-C, выполнив Apple Events самостоятельно и ответив на odoc
(открыть документ; { kCoreEventClass, kAEOpenDocuments }
) сообщение. Чтобы атаковать это, см. Руководство по программированию Apple Events.
Вы должны ожидать написания некоторого фрагмента кода, который устанавливает обработчик событий, например:
err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
NewAEEventHandlerUPP(OpenDocumentsAE), 0, false);
require_noerr(err, CantInstallAppleEventHandler);
И тогда вы на самом деле обработать сообщение в OpenDocumentsAE
(взято из "Обработчик события Apple Open Documents"):
static pascal OSErr OpenDocumentsAE(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
{
AEDescList docList;
FSRef theFSRef;
long index;
long count = 0;
OSErr err = AEGetParamDesc(theAppleEvent,
keyDirectObject, typeAEList, &docList);// 1
require_noerr(err, CantGetDocList);// 2
err = AECountItems(&docList, &count);// 3
require_noerr(err, CantGetCount);
for(index = 1; index <= count; index++)// 4
{
err = AEGetNthPtr(&docList, index, typeFSRef,
NULL, NULL, &theFSRef, sizeof(FSRef), NULL);// 5
require_noerr(err, CantGetDocDescPtr);
err = OpenDocument(&theFSRef);// 6
}
AEDisposeDesc(&docList);// 7
CantGetDocList:
CantGetCount:
CantGetDocDescPtr:
if (err != noErr)// 8
{
// For handlers that expect a reply, add error information here.
}
return(err);// 9
}