Как должно взаимодействовать расширение Finder Sync и главное приложение?
Мой вариант использования: у меня есть MainApp, который выполняет синхронизацию файлов. Мне бы хотелось, чтобы MainApp обрабатывал все вызовы сервера, связанные с синхронизацией, и другие вызовы REST API, такие как обмен документами и т. Д.
С другой стороны, у меня было бы расширение синхронизации Finder, которое показывало бы наложения значков состояния синхронизации. В нем также будет файл-context-menu-item 'Share', который будет отображать диалоговое окно Share, где пользователи могут выбирать, кому поделиться файлом.
Вопросы:
Как должны взаимодействовать Finder Sync Extension и MainApp? Следует ли использовать XCP и если да, то нормально ли, что связь двухсторонняя? Например, MainApp сообщает Finder, что он должен обновиться, потому что некоторые файлы были синхронизированы, а Finder сообщает MainApp, что он должен выполнить операцию "Поделиться".
Кто должен представить диалог "Поделиться"? Если щелкнуть пункт меню "Поделиться" в Finder Sync Extension, должна появиться форма "Поделиться". Должно ли это отображаться расширением Finder или MainApp (при условии, что FinderExtension сообщило, что был выбран элемент "Поделиться").
Если расширение Finder должно представлять форму, то FinderExtension также должно извлекать данные с сервера (например, контакты и группы для совместного использования), и я не уверен, что расширение Finder должно выполнять какие-либо сетевые вызовы к серверу.
Исследуя тему, я нашел несколько подходов:
- Finder Sync Extension и MainApp не взаимодействуют напрямую. Вместо этого FinderExtension считывает данные из базы данных, чтобы правильно отображать значки. В этом сценарии неясно, как FinderExtension должен обновляться после завершения синхронизации или как он должен информировать MainApp для выполнения какого-либо действия.
- XPC связь. Я думаю, FinderExtension может инициировать вызовы MainApp, но ожидается ли обратное направление?
- Есть ли какой-нибудь NotificationCenter между процессами macOS? Я пробовал с
NSWorkspace.sharedWorkspace.notificationCenter
и сNSDistributedNotificationCenter.defaultCenter
но они не доставляют уведомления в MainApp. - mach_ports как в проекте Seafile?
2 ответа
Мне удалось сделать это через CFMessagePort
API. Чтобы иметь изолированное расширение и основное приложение для связи, группы приложений должны быть включены в возможностях XCode. Кроме того, ключ группы приложений с суффиксом (по вашему выбору) должен использоваться в качестве идентификатора порта сообщения.
Основное приложение
Где-то в основном приложении этот вид кода будет прослушивать порт сообщения:
CFMessagePortRef port = CFMessagePortCreateLocal(nil, CFSTR("group.com.yourapp.mach_or_something"), Callback, nil,
nil);
CFRunLoopSourceRef runLoopSource = CFMessagePortCreateRunLoopSource(nil, port, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
Callback
метод реализован как:
static CFDataRef Callback(CFMessagePortRef port, SInt32 messageID, CFDataRef data, void* info)
{
NSData* objcData = (__bridge NSData*) data;
NSLog(@"Message received: %@", [NSString.alloc initWithData:objcData encoding:NSASCIIStringEncoding]);
return data;
}
Расширение Finder Sync
И затем, где-то в расширении (то есть, когда пользователь нажимает на пункт меню):
CFDataRef data = CFDataCreate(NULL, (const UInt8*) "somedata", 8);
SInt32 messageID = 0x1111; // Arbitrary
CFTimeInterval timeout = 1;
CFMessagePortRef remotePort = CFMessagePortCreateRemote(nil, CFSTR("group.com.yourapp.mach_or_something"));
SInt32 status = CFMessagePortSendRequest(remotePort, messageID, data, timeout, timeout, NULL, NULL);
if (status == kCFMessagePortSuccess)
{
NSLog(@"SUCCESS STATUS");
}
else
{
NSLog(@"FAIL STATUS");
}
Это отправит сообщение в основное приложение.
Документация Apple о изолированной среде Mach между процессами:
Семафоры IPC и POSIX и общая память
Обычно приложения для песочницы не могут использовать Mach IPC, семафоры POSIX и разделяемую память или доменные сокеты UNIX (полезно). Однако, указав право, которое запрашивает членство в группе приложений, приложение может использовать эти технологии для связи с другими членами этой группы приложений.
Любой семафор или порт Маха, к которому вы хотите получить доступ в изолированном приложении, должен быть назван в соответствии со специальным соглашением:
Семафоры POSIX и имена совместно используемой памяти должны начинаться с идентификатора группы приложений, за которым следует косая черта (/) и имя по вашему выбору. Имена портов Маха должны начинаться с идентификатора группы приложений, за которым следует точка (.), За которой следует имя по вашему выбору.
Например, если имя вашей группы приложений
Z123456789.com.example.app-group
, вы можете создать два семафора с именемZ123456789.myappgroup/rdyllwflg
а такжеZ123456789.myappgroup/bluwhtflg
, Вы можете создать порт Маха с именемZ123456789.com.example.app-group.Port_of_Kobe
,Примечание. Максимальная длина имени семафора POSIX составляет всего 31 байт, поэтому, если вам нужно использовать семафоры POSIX, вы должны держать короткие имена групп приложений.