应该如何编写带状态的 XPC 服务?

Posted

技术标签:

【中文标题】应该如何编写带状态的 XPC 服务?【英文标题】:How should one write an XPC service with state? 【发布时间】:2014-06-25 08:44:36 【问题描述】:

我已阅读 NSXPC* 文档,该文档建议使出售的服务尽可能无状态。这是一个好主意,至少对于我读过的文档和示例而言,因为服务和调用应用程序将彼此视为单例,并且一次只运行一个服务实例。这意味着这些方法本质上是非成员函数(使用 C++ 术语)。

我为什么要解决这个问题?我想将网络代码放入 XPC。由于 XPC 将使用具有多个窗口的 GUI 应用程序,因此我需要支持多个同时连接。这不适用于单例,至少不能直接使用。

网络 API 是基于 C 的,主要状态类型是指向自定义 struct 的指针。那么我们为什么不做类似的事情呢:

    让创建函数返回一个值类型,如NSUUID 之类的。 (跨进程传递指针是个坏主意。) 在服务中,在NSUUID 和 API C 指针之间创建一个NSDictionary(或std::map 或其他)映射。 各种服务 API 采用 UUID 并将其转换为 C 指针以使用网络 API。

旁白:由于token是随机的,如果XPC服务崩溃,XPC重启后主应用会有一个无用的token。也许我应该使用一个 URL(它将包含所有重新启动的信息)。但是,如果两个连接碰巧在同一台服务器上,我们就会遇到潜在的冲突。也许我可以将这些想法与作为 URL/UUID 对的令牌结合起来。 (UUID 值将从服务返回变为由主应用提供。)

这是实现全状态 XPC 的好方法吗?

【问题讨论】:

鉴于主应用程序和 xpc“从属”之间存在一对一的映射,为什么需要提供任何类型的映射?为什么不采取一种静止状态的方法并提供诸如打开/读取/写入/关闭之类的方法,以便在任何读取之前您知道您需要进行打开等? @***foe,我正在使用现有的基于会话的协议(不是像 HTTP 这样的一次性类型)。想象一下 Apple 的 Safari,它只有一个窗口,只有一个标签;如果我不支持 XPC 中的多个 Internet 连接,就会发生这种情况。再加上 Apple 作弊允许 Safari 使用多个 WebKit XPC 实例,普通程序员是不允许这样做的。 【参考方案1】:

您可能希望向服务接口添加一个方法,该方法使用长期存在的代理对象进行回复。您可以通过调用-[NSXPCInterface setInterface:forSelector:argumentIndex:ofReply:] 来安排此操作,为最后一个参数传递 YES。详情可在此处获得:

https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSXPCInterface_reference/#//apple_ref/occ/instm/NSXPCInterface/setInterface:forSelector:argumentIndex:ofReply:

【讨论】:

以上是关于应该如何编写带状态的 XPC 服务?的主要内容,如果未能解决你的问题,请参考以下文章

在我的 Swift 应用程序中使用来自 XPC 服务的 Objective-C 协议

有没有办法通过 XPC 传递任意结构?

如何在 swift 和 Hal 驱动程序编写的应用程序之间共享数据

如何在 XPC 服务中提供 Swift 类?

XPC 连接如何以线程方式处理?

如何禁用加载/激活 macOS xpc 服务?