该软件包现在是 SwiftSpellbook_macOS 的一部分
sXPC 允许你
XPCTransport 是 sXPC 的一种附加组件,为 XPC 通信提供面向消息的方法。XPCTransport 在客户端和服务端点之间引入了一种稳定的连接
你还可以找到用于 macOS / *OS 开发的 Swift 库
注意:完整的示例代码位于 Sample 文件夹中
public struct TokenRequest: Equatable, Codable {
public var user: String
public var password: String
}
public struct TokenResponse: Equatable, Codable {
public var token: String
public var expiration: Date
}
public protocol TokenService {
func requestToken(_ request: TokenRequest, reply: @escaping (Result<TokenResponse, Error>) -> Void)
}
let connection = TokenServiceXPCConnection(xpc: .service("com.alkenso.XPCService"))
connection.resume()
let proxy = connection.remoteObjectProxy { error in
print(error)
}
let request = TokenRequest(user: "alkenso", password: "1234567_lol")
proxy.requestToken(request) {
print($0)
}
// Define TokenService implementation
struct MockTokenService: TokenService { ... }
// Start listener
let listener = CreateServiceXPCListener(listener: listener)
listener.newConnectionHandler = {
$0.exportedObject = MockTokenService()
$0.resume()
return true
}
listener.resume()
注意:完整的示例代码位于 Sample 文件夹中
假设我们需要实现两个非常常见、接近真实场景的用例
接收/发送的逻辑在另一个进程中实现,我们可以通过 XPC 连接它
// XPCService -> App
public enum RemoteNotification: Codable {
case notify(String)
// first generic parameter - approval text
// second generic parameter - Boolean, indicating request is approved by user
case askApproval(XPCTransportMessage<String, Bool>)
}
// App -> XPCService
public struct AnalyticEvent: Codable {
var reason: String
var date: Date
}
// create XPCTransport connection
let connection = XPCTransportConnection(xpc: .service("com.alkenso.XPCService"))
// setup incoming messages handler
connection.setReceiveMessageHandler(RemoteNotification.self) {
switch $0 {
case .notify(let text):
print("[Notifcation] \(text)")
case .askApproval(let message):
print("[Approval] \(message.request)")
// Reply to XPCTransportMessage
message.reply(.success(true))
}
}
}
// receive connection state updates (react to reconnects)
connection.stateHandler = { print("Connection state: \($0)") }
// all handlers/replies will be called on this queue
connection.queue = .main
// activate connection
connection.activate()
// send analytic event through connection
do {
try connection.send(AnalyticEvent(reason: "Button clicked", date: Date()))
} catch {
print("Failed to send analytic event. Error: \(error)")
}
// create XPCTransport server
let server = XPCTransportServer(.service)
// setup incoming messages handler
server.setReceiveMessageHandler(AnalyticEvent.self) { _, event in
print("Analytic event: \(event)")
}
// activate server
server.activate()
// ... some time later
// send notifications to all connected clients
guard let peer = server.activeConnections.first else { return }
do {
// send simple notification
try server.send(to: peer, message: .notify("You have new message"))
// send approval request that requires reply from the client(s)
let message = XPCTransportMessage<String, Bool>(
request: "New sign in detected on another device. Allow it?",
reply: { approvalResult in
switch approvalResult {
case .success(let approved):
print("Approved: \(approved)")
case .failure(let error):
print("Approval failed: \(error)")
}
}
)
try server.send(to: peer, message: .askApproval(message))
} catch {
print("Failed to send notification to peer. Error: \(error)")
}