Как отправить сообщение из приложения XPC helper в основное приложение?

Мне удалось создать службу XPC и связаться с сервисом XPC, отправив сообщения из основного приложения. Но я хочу знать, можно ли инициировать обмен сообщениями из службы XPC в основное приложение. В документации Apple говорится, что XPC является двунаправленным. Было бы очень признательно, если бы кто-то мог указать мне в правильном направлении на примере.

Пожалуйста, обратите внимание,

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

Я преуспел в первых двух, но не смог найти какой-либо ресурс на третьем.

Благодарю. :)

Ответ 1

Выяснил все. Примером может служить следующий пример:

ProcessorListener.h (входит в состав как клиента, так и сервера):

@protocol Processor

- (void) doProcessing: (void (^)(NSString *response))reply;

@end

@protocol Progress

- (void) updateProgress: (double) currentProgress;
- (void) finished;

@end

@interface ProcessorListener : NSObject<NSXPCListenerDelegate, Processor>

@property (weak) NSXPCConnection *xpcConnection;

@end

ProcessorListener.m: (входит только в сервер)

#import "ProcessorListener.h"

@implementation ProcessorListener

- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
{
    [newConnection setExportedInterface: [NSXPCInterface interfaceWithProtocol:@protocol(Processor)]];
    [newConnection setExportedObject: self];
    self.xpcConnection = newConnection;

    newConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol: @protocol(Progress)];

    // connections start suspended by default, so resume and start receiving them
    [newConnection resume];

    return YES;
}

- (void) doProcessing: (void (^)(NSString *g))reply
{
    dispatch_async(dispatch_get_global_queue(0,0), ^{
      for(int index = 0; index < 60; ++index)
      {
         [NSThread sleepWithTimeInterval: 1];
         [[self.xpcConnection remoteObjectProxy] updateProgress: (double)index / (double)60 * 100];
      }

      [[self.xpcConnection remoteObjectProxy] finished];
    }

    // nil is a valid return value.
    reply(@"This is a reply!");
}

@end

MainApplication.m (ваше главное приложение):

#import "ProcessorListener.h"

- (void) executeRemoteProcess
{
    // Create our connection
    NSXPCInterface * myCookieInterface = [NSXPCInterface interfaceWithProtocol: @protocol(Processor)];

    NSXPCConnection * connection = [[NSXPCConnection alloc] initWithServiceName: kServiceName];

    [connection setRemoteObjectInterface: myCookieInterface];

    connection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(Progress)];
    connection.exportedObject = self;

    [connection resume];

    id<Processor> theProcessor = [connection remoteObjectProxyWithErrorHandler:^(NSError *err)
                       {
                           NSAlert *alert = [[NSAlert alloc] init];
                           [alert addButtonWithTitle: @"OK"];
                           [alert setMessageText: err.localizedDescription];
                           [alert setAlertStyle: NSWarningAlertStyle];

                           [alert performSelectorOnMainThread: @selector(runModal) withObject: nil waitUntilDone: YES];
                       }];

    [theProcessor doProcessing: ^(NSString * response)
     {
        NSLog(@"Received response: %@", response);
     }];
}

#pragma mark -
#pragma mark Progress

- (void) updateProgress: (double) currentProgress
{
    NSLog(@"In progress: %f", currentProgress);
}

- (void) finished
{
    NSLog(@"Has finished!");
}

@end

Обратите внимание, что этот код является сжатой версией, основанной на моем рабочем коде. Он не может составлять 100%, но показывает ключевые понятия. В примере doProcessing запускает async, чтобы показать, что обратные вызовы, определенные в протоколе Progress, по-прежнему выполняются даже после возврата исходного метода и Received response: This is a reply! был зарегистрирован.