Skip to content

macOS 回调式 API

适用版本:0.1 Commercial Beta
适用模块:XHIM
最低版本:macOS 12、Swift 5.9

本页是 macOS 原生开发者的回调 API 入口。所有 onSuccess/onFailure 和事件 回调都在 MainActor 串行执行,可以直接更新 AppKit 或 SwiftUI 状态。macOS 与 iOS 复用 Swift 类型,但本页只说明 macOS 的安装后调用、窗口/进程生命周期、 Sandbox 和文件访问行为。

1. 连接并登录

swift
XHIMClient.connect(
    server:userID:appID:authentication:storageRootURL:
    onConnecting:onConnectSuccess:onConnectFailure:
) -> XHIMRequest
swift
private var client: XHIMClient?
private var connectRequest: XHIMRequest?

connectRequest = XHIMClient.connect(
    server: "https://im-test.example.com",
    userID: "alice",
    onConnecting: {
        print("XHIM macOS connecting")
    },
    onConnectSuccess: { [weak self] client in
        self?.client = client
    },
    onConnectFailure: { error in
        print(error.stableCode, error.message)
    }
)

Production 把宿主已有账号会话转换为 SDK 凭证 Provider。Window 和 ViewController 不接触短期凭证:

swift
connectRequest = XHIMClient.connect(
    server: "https://im.example.com",
    userID: account.userID,
    authentication: .business(AccountService.shared.xhimCredential),
    onConnecting: {},
    onConnectSuccess: { [weak self] in self?.client = $0 },
    onConnectFailure: { [weak self] in self?.show($0.message) }
)
参数类型说明
serverStringXHIM Server HTTPS 基地址
userIDString当前业务用户 ID
appIDString?单租户部署通常省略
authenticationXHIMAuthenticationDevelopment 或业务凭证 Provider
storageRootURLURL?通常省略;默认写入 Application Support 的账号隔离目录

2. 事件监听

swift
private var eventToken: XHIMEventListenerToken?

eventToken = client.addEventListener { [weak self] event in
    switch event {
    case .stateChanged(let state):
        self?.renderConnection(state)
    case .messageUpserted(let change),
         .messageStateChanged(let change):
        self?.reloadMessages(conversationID: change.conversationID)
    case .conversationChanged:
        self?.reloadConversations()
    case .presenceChanged(let update):
        self?.renderPresence(update)
    case .typingChanged(let update):
        self?.renderTyping(update)
    default:
        break
    }
}

XHIMEventListenerToken 必须由账号 Session 持有,不能只存在局部变量。多窗口 共享一个 Client,可以各自安装监听并在窗口释放时取消自己的 token。

3. 单聊与文字消息

swift
client.directConversation(
    with: "bob",
    onSuccess: { [weak self] conversation in
        self?.client?.sendText(
            conversationID: conversation.conversationID,
            text: "Hello from macOS",
            onSuccess: { _ in print("message queued") },
            onFailure: { print($0.stableCode, $0.message) }
        )
    },
    onFailure: { print($0.stableCode, $0.message) }
)

sendText 成功表示消息进入可靠 Outbox,不表示对端已读。页面通过 messageStateChanged 后重查消息,通过已读事件后重查会话/同伴已读。

4. 会话和消息分页

swift
client.conversations(
    limit: 50,
    onSuccess: { [weak self] in self?.conversations = $0.conversations },
    onFailure: { print($0.stableCode, $0.message) }
)

client.messages(
    conversationID: conversationID,
    limit: 50,
    onSuccess: { [weak self] in self?.messages = $0.messages },
    onFailure: { print($0.stableCode, $0.message) }
)

分页 Cursor 是不透明 Data,只能原样传回同一查询。不要从 SQLite 自己拼会话 或未读数。

5. 自定义消息

swift
let message = XHIMOutgoingMessage(
    contentType: "com.example.order.card",
    contentVersion: 1,
    payload: Data(#"{"orderID":"20260728001"}"#.utf8),
    fallbackText: "[订单] 20260728001"
)

client.sendMessage(
    conversationID: conversationID,
    message: message,
    onSuccess: { _ in print("custom message queued") },
    onFailure: { print($0.stableCode, $0.message) }
)

未知 contentType 必须显示 fallbackText。Renderer 只负责展示,不改变协议 payload。

6. 附件和安全作用域

通过 NSOpenPanel 取得用户选择的 URL;启用 Sandbox 时只在读取/提交期间访问 安全作用域:

swift
guard url.startAccessingSecurityScopedResource() else { return }
defer { url.stopAccessingSecurityScopedResource() }

client.sendFile(
    conversationID: conversationID,
    fileURL: url,
    displayName: url.lastPathComponent,
    onSuccess: { _ in print("file task accepted") },
    onFailure: { print($0.stableCode, $0.message) }
)

上传任务由 Core 持久化。Window 关闭不取消附件任务;需要业务取消时调用 cancelMediaTask

7. 请求取消、登出和进程退出

swift
let request = client.searchMessages(
    keyword: keyword,
    limit: 50,
    onSuccess: { [weak self] in self?.results = $0.messages },
    onFailure: { error in
        if error.stableCode != "request_cancelled" {
            print(error.message)
        }
    }
)

request.cancel()

普通 XHIMRequest.cancel() 只取消本次等待;已经进入 Outbox 的消息使用 cancelMessage,媒体使用 cancelMediaTask。账号退出调用 logout;应用终止 或账号容器销毁时调用 shutdown。关闭最后一个 Window 不应自动销毁 Client。

8. 回调错误

XHIMCallbackError 的稳定字段:

字段用途
stableCode业务分支,不匹配 message 文案
retryable是否适合用户重试
retryAfterMilliseconds服务端建议的最短等待
userAction登录、升级、释放空间或联系支持
operationID / traceID脱敏诊断与服务端追踪

所有业务 API 的模型、约束和事件载荷继续按模块查阅 SDK API Reference。macOS 的 App Sandbox、窗口管理、睡眠唤醒 和发布验收见 macOS QuickStart

XHIM 客户端 SDK 与服务端文档