Macos 如何从XPC helper应用程序向主应用程序发送消息?
我成功地创建了XPC服务,并通过从主应用程序发送消息与XPC服务通信。但我想知道的是,是否可以启动从XPC服务到主应用程序的通信。表示XPC是双向的。如果有人能举个例子给我指出正确的方向,我将不胜感激 请注意Macos 如何从XPC helper应用程序向主应用程序发送消息?,macos,cocoa,xpc,nsxpcconnection,Macos,Cocoa,Xpc,Nsxpcconnection,我成功地创建了XPC服务,并通过从主应用程序发送消息与XPC服务通信。但我想知道的是,是否可以启动从XPC服务到主应用程序的通信。表示XPC是双向的。如果有人能举个例子给我指出正确的方向,我将不胜感激 请注意 我想从主应用程序启动XPC 从主应用程序与XPC通信 当一些事件发生时,XPC应该向主应用程序发送一条消息 前两个我都成功了,但第三个我找不到任何资源 谢谢。:) 把一切都弄明白了。以下是一个不错的例子: ProcessorListener.h(包括在客户端和服务器中): @协议处理器
- 我想从主应用程序启动XPC
- 从主应用程序与XPC通信
- 当一些事件发生时,XPC应该向主应用程序发送一条消息
谢谢。:) 把一切都弄明白了。以下是一个不错的例子: ProcessorListener.h(包括在客户端和服务器中):
@协议处理器
-(void)数据处理:(void(^)(NSString*response))应答;
@结束
@协议进展
-(void)updateProgress:(双)currentProgress;
-(无效)已完成;
@结束
@接口处理器Listener:NSObject
@属性(弱)NSXPCConnection*xpcConnection;
@结束
ProcessorListener.m:(仅包含在服务器中)
#导入“ProcessorListener.h”
@实现处理器Listener
-(BOOL)侦听器:(NSXPCListener*)侦听器应接受新连接:(NSXPCConnection*)新连接
{
[新连接集导出接口:[NSXPCInterface interface interface with protocol:@protocol(Processor)];
[新连接设置导出对象:self];
self.xpcConnection=newConnection;
newConnection.remoteObjectInterface=[NSXPCInterface Interface WithProtocol:@protocol(Progress)];
//默认情况下,连接开始挂起,因此请继续并开始接收它们
[新连接恢复];
返回YES;
}
-(void)数据处理:(void(^)(NSString*g))回复
{
调度异步(调度获取全局队列(0,0)^{
对于(int索引=0;索引<60;++索引)
{
[NSThread sleepWithTimeInterval:1];
[[self.xpcConnection remoteObjectProxy]updateProgress:(双)索引/(双)60*100];
}
[[self.xpcConnection remoteObjectProxy]完成];
}
//nil是一个有效的返回值。
答复(@“这是答复!”);
}
@结束
MainApplication.m(您的主应用程序):
#导入“ProcessorListener.h”
-(void)ExecuteMoteProcess
{
//建立我们的联系
NSXPCInterface*myCookieInterface=[NSXPCInterface interfaceWithProtocol:@协议(处理器)];
NSXPCConnection*连接=[[NSXPCConnection alloc]initWithServiceName:kServiceName];
[connection setRemoteObjectInterface:MyOkieInterface];
connection.exportedInterface=[NSXPCInterface interface interface with protocol:@protocol(Progress)];
connection.exportedObject=self;
[连接恢复];
id处理器=[connection remoteObjectProxyWithErrorHandler:^(n错误*错误)
{
NSAlert*警报=[[NSAlert alloc]init];
[标题为@“确定”的警报添加按钮];
[alert setMessageText:err.localizedDescription];
[警报设置警报样式:NSWarningAlertStyle];
[alert performSelectorOnMainThread:@selector(runModal)with object:nil waitUntilDone:YES];
}];
[处理器数据处理:^(NSString*响应)
{
NSLog(@“收到的响应:%@”,响应);
}];
}
#布拉格标记-
#布拉格语标记进展
-(void)updateProgress:(双)currentProgress
{
NSLog(@“进行中:%f”,currentProgress);
}
-(无效)完成
{
NSLog(@“已完成!”);
}
@结束
请注意,此代码是基于我的工作代码的浓缩版本。它可能不会100%编译,但显示了使用的关键概念。在示例中,
doProcessing
运行异步,以显示即使在初始方法返回且收到响应后,Progress
协议中定义的回调仍会执行onse:这是一个回复!
已被记录。您在回调主程序方面做了哪些尝试?您是否尝试使用主程序中的exportedMethods
和exportedObject
?是的,我正在尝试使用XPC服务中的remoteObjectInterface
和主应用程序中的ExportedObject
上。如果您能提供一个示例,我将非常高兴。向我们展示您尝试过的内容,我们将尝试帮助您修复。如果处理器有多个连接,该怎么办?我如何知道哪个连接称为doProcessing
,以便我可以向其报告进度?@pointum您可以将另一个标识进程的参数传递到doProcessing
。这是一个很好的答案,但为什么不在定义不同的部分和内容时讨论应用程序和服务,而不是客户端和服务器呢?其中的秘密在于“服务器”必须在特定的上下文中运行。我的意思是,如果您从gdb或命令行运行服务器,这是行不通的。
@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
#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
#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