Общайтесь с другим приложением с помощью XPC
У меня есть оконное приложение, и для добавления некоторых функций мне нужно другое приложение, которое запускается при входе в систему и синхронизирует данные с сервером, если доступно.
Я пытался с NSDistributionNotification, но это практически бесполезно в изолированном приложении. Я посмотрел XPC и надеялся, что он будет работать, но я просто не знаю, как заставить его работать с помощником. До сих пор я сделал это с помощью XPC.
Основное приложение
NSXPCInterface *remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(AddProtocol)];
NSXPCConnection *xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.example.SampleService"];
xpcConnection.remoteObjectInterface = remoteInterface;
xpcConnection.interruptionHandler = ^{
NSLog(@"Connection Terminated");
};
xpcConnection.invalidationHandler = ^{
NSLog(@"Connection Invalidated");
};
[xpcConnection resume];
NSInteger num1 = [_number1Input.stringValue integerValue];
NSInteger num2 = [_number2Input.stringValue integerValue];
[xpcConnection.remoteObjectProxy add:num1 to:num2 reply:^(NSInteger result) {
NSLog(@"Result of %d + %d = %d", (int) num1, (int) num2, (int) result);
}];
XPC Сервис
In main () ...
SampleListener *delegate = [[SampleListener alloc] init];
NSXPCListener *listener = [NSXPCListener serviceListener];
listener.delegate = delegate;
[listener resume];
// In delegate
-(BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(AddProtocol)];
newConnection.exportedInterface = interface;
newConnection.exportedObject = [[SampleObject alloc] init];
[newConnection resume];
return YES;
}
// In Exported Object class
-(void)add:(NSInteger)num1 to:(NSInteger)num2 reply:(void (^)(NSInteger))respondBack {
resultOfAddition = num1 + num2;
respondBack(resultOfAddition);
}
Это работает нормально, теперь мне нужно передать этот результат в приложение Helper. Как я могу это сделать? Если XPC не является ответом здесь, чтобы общаться, то какой я должен использовать? Любые указатели, пожалуйста?
2 ответа
Ладно, для всех, кто боролся с этим, я наконец смог на 100% установить связь между двумя процессами приложения, используя NSXPCConnection
Ключ к сведению, что вы можете только создать NSXPCConnection
до трех вещей.
- XPCService. Вы можете подключиться к XPCService строго через имя
- Маха Сервис. Вы также можете подключиться к службе Mach строго через имя
-
NSXPCEndpoint
, Это то, что мы ищем, чтобы общаться между двумя прикладными процессами.
Проблема в том, что мы не можем напрямую передать NSXPCEndpoint
из одного приложения в другое.
Он включал создание агента запуска machservice ( см. Этот пример, как это сделать), который содержал NSXPCEndpoint
имущество. Одно приложение может подключиться к machservice и установить это свойство на свое собственное [NSXPCListener anonymousListener].endpoint
Затем другое приложение может подключиться к machservice и запросить эту конечную точку.
Затем, используя эту конечную точку, NSXPCConnection
может быть создан, который успешно установил мост между двумя приложениями. Я проверил отправку объектов туда и обратно, и все работает как положено.
Обратите внимание, что если ваше приложение находится в "песочнице", вам придется создать XPCService
как посредник между вашим Приложением и Machservice
Я очень рад, что у меня все получилось - я довольно активен в SO, поэтому, если кто-то заинтересован в исходном коде, просто добавьте комментарий, и я могу приложить усилия, чтобы опубликовать больше деталей
Некоторые препятствия, с которыми я столкнулся:
Вы должны запустить свой machservice, это строки:
OSStatus err;
AuthorizationExternalForm extForm;
err = AuthorizationCreate(NULL, NULL, 0, &self->_authRef);
if (err == errAuthorizationSuccess) {
NSLog(@"SUCCESS AUTHORIZING DAEMON");
}
assert(err == errAuthorizationSuccess);
Boolean success;
CFErrorRef error;
success = SMJobBless(
kSMDomainSystemLaunchd,
CFSTR("DAEMON IDENTIFIER HERE"),
self->_authRef,
&error
);
Кроме того, каждый раз, когда вы перестраиваете своего демона, вы должны выгружать предыдущий агент запуска с помощью следующих команд bash:
sudo launchctl unload /Library/LaunchDaemons/com.example.apple-samplecode.EBAS.HelperTool.plist
sudo rm /Library/LaunchDaemons/com.example.apple-samplecode.EBAS.HelperTool.plist
sudo rm /Library/PrivilegedHelperTools/com.example.apple-samplecode.EBAS.HelperTool
(С вашими соответствующими идентификаторами, конечно)
Если вы ищете, как это сделать в Swift. Я написал руководство о том, как это сделать:
https://rderik.com/blog/creating-a-launch-agent-that-provides-an-xpc-service-on-macos/
Вы должны сначала создать Launch Agent (или демон, если вам нужны дополнительные привилегии), который предоставляет службу XPC. Служба XPC будет зарегистрирована как служба mach, которую предоставляет ваш агент. Таким образом, вашему агенту придется создать слушателя, подобного следующему:
let listener = NSXPCListener(machServiceName: "com.rderik.exampleXPC" )
И чтобы использовать эту услугу от другого клиента, вам нужно создатьNSXPCConnection
к тому сервису. Как это:
let connection = NSXPCConnection(machServiceName: "com.rderik.exampleXPC")
За кулисами, упрощение того, что происходит, заключается в том, что ваш агент зарегистрирует вашу службу mach в launchd
. Когда ваш "клиент" хочет подключиться к сервису machlaunchd
он уже будет зарегистрирован, поэтому он установит связь между ними.
Надеюсь, это поможет.
Я думаю, я понял, как это сделать. Все, что вам нужно сделать, это создать вспомогательный инструмент командной строки в XCode, установить его как задание Launchd (либо демон, либо агент в зависимости от требований привилегий). Вы можете использовать определенный протокол для связи с вспомогательным инструментом. Обратитесь к приведенному ниже образцу кода от Apple, чтобы понять, как это делается.
Образец кода от Apple: https://developer.apple.com/library/mac/samplecode/EvenBetterAuthorizationSample/Listings/Read_Me_About_EvenBetterAuthorizationSample_txt.html
Прочитайте приведенную ниже ссылку, чтобы понять, что вы действительно хотите, демон или агент: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/DesigningDaemons.html