消息创建、收发与历史检索 (Message)
QXJIMSDK 的消息流程分为两步:
- 同步构造消息 (
create*Message):生成带唯一clientMsgID与初始状态.sending的IMMessage结构体(可立即插入聊天列表展示“发送中”气泡)。 - 异步发送消息 (
sendMessage/sendMessageNotOss):将消息通过 WebSocket 发送至服务端(若为图片/语音/视频/文件消息,SDK 会自动完成分片上传并通过onProgress回调上传进度)。
1. 创建各类消息
let client = QXJIMClient.shared
// 1. 纯文本消息
let textMsg = try client.createTextMessage(text: "你好!")
// 2. 群聊 @ 消息(支持 @所有人 client.atAllTag)
let atMsg = try client.createTextAtMessage(
text: "@张三 @所有人 请查收",
atUserIDs: ["u_1002", client.atAllTag],
atUsersInfo: [
IMAtInfo(atUserID: "u_1002", groupNickname: "张三"),
IMAtInfo(atUserID: client.atAllTag, groupNickname: "所有人")
],
quoteMessage: nil
)
// 3. 引用回复消息
let quoteMsg = try client.createQuoteMessage(
text: "同意这个方案",
quoteMessage: textMsg
)
// 4. 图片消息(传入本地沙盒绝对路径)
let imgMsg = try client.createImageMessageFromFullPath(imageFullPath: "/path/to/photo.jpg")
// 5. 语音消息(绝对路径 + 秒数)
let soundMsg = try client.createSoundMessageFromFullPath(soundPath: "/path/to/voice.m4a", duration: 12)
// 6. 视频消息(视频路径 + 格式 + 时长秒数 + 封面图路径)
let videoMsg = try client.createVideoMessageFromFullPath(
videoFullPath: "/path/to/video.mp4",
videoType: "mp4",
duration: 30,
snapshotFullPath: "/path/to/thumb.jpg"
)
// 7. 文件消息
let fileMsg = try client.createFileMessageFromFullPath(
fileFullPath: "/path/to/report.pdf",
fileName: "report.pdf"
)
// 8. 位置消息
let locMsg = try client.createLocationMessage(
description: "上海市浦东新区陆家嘴",
longitude: 121.4997,
latitude: 31.2397
)
// 9. 名片消息
let cardMsg = try client.createCardMessage(
card: IMCardElem(userID: "u_1003", nickname: "李四", faceURL: "https://...")
)
// 10. 自定义业务消息(如红包、打卡、音视频通话卡片等)
let customMsg = try client.createCustomMessage(
data: "{\"type\":\"red_packet\",\"id\":\"rp_001\"}",
extensionData: "",
description: "[红包]"
)
// 11. 合并转发与单条转发
let mergerMsg = try client.createMergerMessage(
messages: [textMsg, quoteMsg],
title: "群聊的聊天记录",
summaryList: ["张三: 你好!", "李四: 同意这个方案"]
)
let forwardMsg = try client.createForwardMessage(message: textMsg)
2. 发送消息 (sendMessage)
- 单聊:传入
recvID: "对方UserID",groupID: "" - 群聊:传入
recvID: "",groupID: "目标GroupID"
let sentMsg = try await QXJIMClient.shared.sendMessage(
message: imgMsg,
recvID: "u_10002",
groupID: "",
offlinePushInfo: IMOfflinePushInfo(
title: "收到一条新消息",
desc: "[图片]"
),
isOnlineOnly: false
) { progress in
print("附件上传进度: \(progress)%")
}
print("发送成功,服务端消息 ID: \(sentMsg.serverMsgID ?? "")")
3. 拉取历史消息(下拉加载更多)
// 首次进入聊天页:startClientMsgID 传 "",拉取最新 20 条消息
let firstPage = try await QXJIMClient.shared.getAdvancedHistoryMessageList(
params: IMHistoryMessageListParams(
conversationID: convID,
startClientMsgID: "",
count: 20
)
)
let messages: [IMMessage] = firstPage.messageList ?? []
let hasNoMore: Bool = firstPage.isEnd ?? false
// 下拉加载更早的历史消息:传入当前列表最顶部消息的 clientMsgID
if let oldestMsgID = messages.first?.clientMsgID, !hasNoMore {
let nextPage = try await QXJIMClient.shared.getAdvancedHistoryMessageList(
params: IMHistoryMessageListParams(
conversationID: convID,
startClientMsgID: oldestMsgID,
count: 20
)
)
}
4. 消息撤回、删除与本地搜索
// 1. 撤回消息(双方都会收到 .messageRevoked 事 件)
try await QXJIMClient.shared.revokeMessage(
conversationID: convID,
clientMsgID: msg.clientMsgID!
)
// 2. 删除消息(同时删除本地与服务端)
try await QXJIMClient.shared.deleteMessage(
conversationID: convID,
clientMsgID: msg.clientMsgID!
)
// 3. 搜索本地聊天记录(例如搜索包含“合同”的文本消息或搜索会话内所有图片消息)
let searchResult = try await QXJIMClient.shared.searchLocalMessages(
params: IMSearchLocalMessagesParams(
conversationID: convID, // 传 "" 则全局跨会话搜索
keywordList: ["合同"],
messageTypeList: [Int(IMMessageContentType.text.rawValue)],
pageIndex: 1,
count: 20
)
)