Build Status Platforms Documentation Matrix

AsyncXPCConnection

Swift 并发支持 NSXPCConnection

特性

您可能会想直接将 XPC 接口函数设为异步。虽然编译器支持这种做法,但它非常不安全。这种方法无法处理连接失败,并会导致程序挂起。

用法

给定一个如下的 XPC 服务

@objc
protocol XPCService {
    func method()
    func errorMethod(reply: (Error?) -> Void)
    func valueAndErrorMethod(reply: (String?, Error?) -> Void)
    func dataAndErrorMethod(reply: (Data?, Error?) -> Void)
}

您可以直接使用 NSXCPConnection

let conn = NSXPCConnection()
conn.remoteObjectInterface = NSXPCInterface(with: XPCService.self)

// access to the underlying continuation
try await conn.withContinuation { (service: XPCService, continuation: CheckedContinuation<Void, Error>) in
    service.errorMethod() {
        if let error = $0 {
            continuation.resume(throwing: error)
        } else {
            continuation.resume()
        }
    }
}

try await conn.withService { (service: XPCService) in
    service.method()
}

try await conn.withErrorCompletion { (service: XPCService, handler) in
	service.errorMethod(reply: handler)
}

let value = try await conn.withValueErrorCompletion { (service: XPCService, handler) in
    service.valueAndErrorMethod(reply: handler)
}

let decodedValue = try await conn.withDecodingCompletion { (service: XPCService, handler) in
    service.dataAndErrorMethod(reply: handler)
}

您还可以使用 RemoteXPCService 类型,这将消除对服务的显式类型指定的需求。

let conn = NSXPCConnection()
let remote = RemoteXPCService<XPCService>(connection: conn, remoteInterface: XPCService.self)

let decodedValue = try await remote.withDecodingCompletion { service, handler in
    service.dataAndErrorMethod(reply: handler)
}

排序

QueuedRemoteXPCService 类型与 RemoteXPCService 非常相似,但提供了一个排队接口来控制消息传递的顺序。这是通过 AsyncQueuing 协议完成的,用于灵活的、无依赖的支持。如果您需要兼容的队列实现,请查看 Queue。如果您知道其他的,请告诉我,我可以链接到它。

import AsyncXPCConnection
import Queue

extension AsyncQueue: AsyncQueuing {}

let queue = AsyncQueue()
let connection = NSXPCConnection()
let queuedService = QueuedRemoteXPCService<XPCService, AsyncQueue>(queue: queue, provider: { connection })

queuedService.addOperation { service in
    service.method()
}

let value = try await queuedService.addDecodingOperation { service, handler in
    service.dataAndErrorMethod(reply: handler)
}

替代方案

贡献和协作

我很乐意收到您的来信! Issue 或 Pull Request 非常有效。 Matrix spaceDiscord 都可用于实时帮助,但我强烈倾向于以文档的形式回答。您也可以在 mastodon 上找到我。

我更喜欢协作,如果您有类似的项目,我很乐意找到合作的方式。

我更喜欢使用制表符进行缩进以提高可访问性。 但是,我宁愿您使用您想要的系统并提出 PR,而不是因为空格而犹豫。

通过参与此项目,您同意遵守贡献者行为准则