跳到主要内容

实时事件流监听 (AsyncStream)

与原版 Objective-C OpenIMSDK 采用单点 Delegate 回调不同,QXJIMSDK 内置了线程安全的多播事件广播器 IMEventBroadcaster,将底层全部 7 大监听器转换为标准 Swift AsyncStream。

  • 支持多处同时订阅:例如会话列表 ViewModel 与聊天详情页 ViewModel 可以同时订阅 messageEvents.stream(),互不干扰、不会互相覆盖。
  • 自动生命周期管理:当承载 for await 的 Swift Task 被 cancel()(如 SwiftUI 视图 .task {} 随页面销毁自动取消)时,IMEventBroadcaster 会通过 onTermination 自动清理对应的 Continuation,无内存泄漏。

1. 事件流一览表​

多播流属性 (QXJIMClient.shared)事件元素类型对应底层监听协议
connectionEvents.stream()IMConnectionEventOnConnListener
conversationEvents.stream()IMConversationEventOnConversationListener
inputStatusEvents.stream()IMInputStatusChangedDataonConversationUserInputStatusChanged (专项流)
messageEvents.stream()IMMessageEventOnAdvancedMsgListener
groupEvents.stream()IMGroupEventOnGroupListener
friendshipEvents.stream()IMFriendshipEventOnFriendshipListener
userEvents.stream()IMUserEventOnUserListener
userStatusEvents.stream()IMUserOnlineStatusonUserStatusChanged (专项流)
customBusinessEvents.stream()String (JSON)OnCustomBusinessListener

2. 在 SwiftUI / ViewModel 中订阅示例​

2.1 监听连接与 Token 状态 (connectionEvents)​

Task {
for await event in QXJIMClient.shared.connectionEvents.stream() {
switch event {
case .connecting:
print("正在连接 IM 服务器...")
case .connected:
print("IM 服务器连接成功")
case .connectFailed(let error):
print("IM 连接失败: \(error.localizedDescription)")
case .kickedOffline:
print("当前账号在其他设备登录,已被踢下线")
case .userTokenExpired:
print("IM Token 已过期,请重新登录")
case .userTokenInvalid(let reason):
print("IM Token 无效: \(reason)")
}
}
}

2.2 监听会话变更与数据同步进度 (conversationEvents)​

Task {
for await event in QXJIMClient.shared.conversationEvents.stream() {
switch event {
case .syncServerStart(let reinstalled):
print("开始同步服务端会话数据 (是否重装: \(reinstalled))")
case .syncServerProgress(let progress):
print("同步进度: \(progress)%")
case .syncServerFinish:
print("服务端会话数据同步完成")
case .syncServerFailed:
print("服务端会话数据同步失败")
case .newConversations(let list), .conversationsChanged(let list):
// 局部增量更新本地会话列表 UI
await updateConversationListUI(with: list)
case .totalUnreadCountChanged(let totalUnread):
// 更新底部 TabBar 消息未读角标
await updateTabBadge(count: Int(totalUnread))
case .userInputStatusChanged(let inputData):
print("用户 \(inputData.userID) 正在输入: \(inputData.isTyping)")
}
}
}

2.3 监听新消息、已读回执与消息撤回 (messageEvents)​

Task {
for await event in QXJIMClient.shared.messageEvents.stream() {
switch event {
case .receivedNewMessage(let msg):
await appendIncomingMessage(msg)
case .receivedOfflineNewMessage(let msg):
await appendIncomingMessage(msg)
case .receivedOnlineOnlyMessage(let msg):
await handleSignalingOrOnlineOnlyMessage(msg)
case .c2cReadReceipts(let receipts):
await markLocalMessagesAsReadByPeer(receipts)
case .messageRevoked(let revokedInfo):
await markLocalMessageAsRevoked(revokedInfo)
case .messageDeleted(let deletedMsg):
await removeMessageFromUI(deletedMsg.clientMsgID)
}
}
}