消息
<p>[TOC]</p>
<h2>会话和消息</h2>
<p>SDK 中用户与同一个对象的聊天信息集合,称为一个会话,用 QDSession 来表示。会话有单人会话,群组会话等类型。
原型</p>
<pre><code>typedef NS_ENUM(NSInteger, QDSessionType) {
QDSessionTypeP2P = 0, /** 单聊会话*/
QDSessionTypeGroup = 1, /** 群组会话*/
QDSessionTypeChatroom = 2, /** 聊天室 暂时未启用*/
QDSessionTypeApp = 3, /** 应用消息 移动端不支持发送*/
QDSessionTypeMiLiao = 4, /** 密聊消息类型*/
};
@interface QDSession : NSObject<NSCopying>
/**
* 会话ID,如果当前session为group,则sessionId为groupId,如果是P2P则为对方帐号
*/
@property (nonatomic, copy, readonly) NSString *sessionId;
/**
* 会话类型
*/
@property (nonatomic, assign, readonly) QDSessionType sessionType;
/**
* 通过id、type和extType构造会话对象
*
* @param sessionId 会话ID
* @param sessionType 会话类型
* @return 会话对象实例
*/
+ (instancetype)session:(NSString *)sessionId type:(QDSessionType)sessionType;
@end</code></pre>
<p>在使用的时候,不需要去 SDK 获取会话对象,直接根据已有的会话 Id 和 类型构造出即可。</p>
<p>示例</p>
<pre><code>//p2p
QDSession *myFriendSession = [QDSession session:@"friend user id" type:QDSessionTypeP2P];
//team
QDSession *teamSession = [QDSession session:@"team id" type:QDSessionTypeGroup];
//do something with session</code></pre>
<p>SDK 中用于表示消息的结构为 QDMessage。消息属于即时通讯中最关键最重要的类,它是传递信息的基本模型。</p>
<p>原型</p>
<pre><code>@interface QDMessage : NSObject
/**
* 消息ID,唯一标识
*/
@property (nonatomic, copy ) NSString *messageId;
/**
* 引用消息的消息ID
*/
@property (nonatomic, copy ) NSString *sourcemsgId;
/**
* 消息类型
*/
@property (nonatomic, assign) QDMessageType messageType;
/**
* 消息信息标示 2:强通知 4:签收消息
*/
@property (nonatomic, assign) NSInteger msgFlag;
/**
* 所属会话
*/
@property (nonatomic, strong) QDSession *session;
/**
* 消息发送者id
*/
@property (nonatomic, copy) NSString *senderId;
/**
* 消息发送者名字
*/
@property (nonatomic, copy) NSString *senderName;
/**
* 消息发送者头像信息
*/
@property (nonatomic, copy) NSString *senderAvatar;
/**
* 消息标题
*/
@property (nonatomic, copy) NSString *title;
/**
* 消息文本
* @discussion 消息中除 QDMessageTypeText 外,其他消息 text 字段都为 nil 如果text文本长度超过 1000 则会截取到 1000
*/
@property (nonatomic, strong) NSString *text;
/**
* 消息内容信息
*/
@property (nonatomic, copy) NSString *content;
/**
* 消息附件内容
*/
@property (nullable, nonatomic, strong) id<QDMessageObject> messageObject;
/**
* 附件信息
*/
@property (nullable, nonatomic, copy) NSString *attachments;
/**
* 服务端扩展字段
*/
@property (nonatomic, strong) id remoteExt;
/**
* 客户端本地扩展
*/
@property (nonatomic, strong) NSDictionary *localExt;
/**
* 消息发送时间(纳秒级)
*
* @discussion 本地存储消息可以通过修改时间戳来调整其在会话列表中的位置,发完服务器的消息时间戳将被服务器自动修正
*/
@property (nonatomic, assign) NSTimeInterval timestamp;
/**
* 消息是否被播放过
*/
@property (nonatomic, assign) BOOL isPlayed;
/**
* 消息是否需要被计入未读计数
** @discussion 默认为YES。默认情况下,用户收到的所有消息都会被计入未读。设置这个为NO后,对应的消息被对端接受后将不计入未读消息计数内。
*/
@property (nonatomic, assign) BOOL shouldBeCounted;
/**
* 消息打开时间
*/
@property (nonatomic, assign) NSTimeInterval openTimestamp;
/**
* 是否是往外发的消息
*/
@property (nonatomic, assign, readonly) BOOL isOutgoingMsg;
/**
* 是否是收到的消息
*
* @discussion 由于有漫游消息的概念,所以自己发出的消息漫游下来后仍旧是"收到的消息",这个字段用于消息出错是时判断需要重发还是重收
*/
@property (nonatomic, assign, readonly) BOOL isReceivedMsg;
/**
* 消息是否标记为已删除
*
* @discussion 已删除的消息在获取本地消息列表时会被过滤掉,只有根据 messageId 获取消息的接口可能会返回已删除消息
*/
@property (nonatomic, assign, readonly) BOOL isDeleted;
/**
* 对端是否已读
* @discussion 只有当当前消息为 P2P 消息且 isOutgoingMsg 为 YES 时这个字段才有效,需要对端调用过发送已读回执的接口
*/
@property (nonatomic, assign, readonly) BOOL isRemoteRead;
/**
* 是否本地已读
* @discussion 标记未读消息使用
*/
@property (nonatomic, assign, readonly) BOOL isLocalRead;
/**
* 发送者客户端类型
*/
@property (nonatomic, assign, readonly) QDPlatfromType senderClientType;
/**
* 消息发送状态
*/
@property (nonatomic, assign, readonly) QDMessageStatus status;
/**
* 消息投递状态 仅针对发送的消息
*/
@property (nonatomic, assign, readonly) QDMessageDeliveryState deliveryState;
/**
* 消息附件下载状态 仅针对收到的消息
*/
@property (nonatomic, assign, readonly) QDMessageAttachmentDownloadState attachmentDownloadState;
/**
* 会话Id(服务端使用)
*/
@property (nonatomic, copy) NSString *conversationId;
/**
* 消息序号
*/
@property (nonatomic, assign) unsigned long long msgnum;
/**
* 发送者的消息序号
*/
@property (nonatomic, assign) unsigned long long senderMsgnum;
@end</code></pre>
<p>上述消息的状态属性,推荐只在主线程对这些属性进行读写</p>
<p>目前提供如下几种消息类型,不同的消息类型对应不同的 MessageObject</p>
<table>
<thead>
<tr>
<th style="text-align: center;">消息格式</th>
<th style="text-align: center;">MessageObject</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">文本消息</td>
<td style="text-align: center;">nil</td>
</tr>
<tr>
<td style="text-align: center;">图片消息</td>
<td style="text-align: center;">QDImageObject</td>
</tr>
<tr>
<td style="text-align: center;">音频消息</td>
<td style="text-align: center;">QDAudioObject</td>
</tr>
<tr>
<td style="text-align: center;">视频消息</td>
<td style="text-align: center;">QDVideoObject</td>
</tr>
<tr>
<td style="text-align: center;">文件消息</td>
<td style="text-align: center;">QDFileObject</td>
</tr>
<tr>
<td style="text-align: center;">地理位置消息</td>
<td style="text-align: center;">QDLocationObject</td>
</tr>
<tr>
<td style="text-align: center;">通知消息</td>
<td style="text-align: center;">QDNotificationObject</td>
</tr>
<tr>
<td style="text-align: center;">提醒消息</td>
<td style="text-align: center;">QDTipObject</td>
</tr>
</tbody>
</table>
<h2>消息发送</h2>
<p>开发者需要通过 QDClient 里的 QDIMChatManager 协议进行消息发送</p>
<p>原型</p>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
* 发送消息
*
* @param message 消息 (暂不支持提醒消息)
* @param session 接受方
* @param error 错误 如果在准备发送消息阶段发生错误,这个error会被填充相应的信息
* @return 是否调用成功,这里返回的 result 只是表示当前这个函数调用是否成功,需要后续的回调才能够判断消息是否已经发送至服务器
*/
- (BOOL)sendMessage:(QDMessage *)message toSession:(QDSession *)session error:(NSError * _Nullable *)error;
@end</code></pre>
<p>属性列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">message</td>
<td style="text-align: center;">QDMessage</td>
<td style="text-align: center;">需要发送的消息,开发者构造出 message 后,需要选择构造对应的 messageObject (文本消息直接填入 text 即可,无须消息附件注入),即可传入此接口进行发送</td>
</tr>
<tr>
<td style="text-align: center;">session</td>
<td style="text-align: center;">QDSession</td>
<td style="text-align: center;">需要发送到的会话</td>
</tr>
<tr>
<td style="text-align: center;">error</td>
<td style="text-align: center;">NSError</td>
<td style="text-align: center;">开发者需要自己构造出一个 NSError 对象,并将对象引用传入。如果在准备发送消息阶段发生错误,这个对象会被填充相应的信息。通常为参数检查错误或者登录状态错误,可参考错误码说明定位具体的出错类型</td>
</tr>
</tbody>
</table>
<p>1 文本消息。</p>
<p>以发送一条文本消息 <code>hello Qida</code> 至好友Id 为 <code>account</code> 的业务场景</p>
<pre><code>// 构造出具体会话
QDSession *session = [QDSession session:@"account" type:QDSessionTypeP2P];
// 构造出具体消息
QDMessage *message = [[QDMessage alloc] init];
message.text = @"hello Qida";
// 错误反馈
NSError *error = nil;
// 发送消息
[[QDClient sharedClient].chatManager sendMessage:message toSession:session error:&error];</code></pre>
<p>2 图片消息。</p>
<p>附件原型:</p>
<pre><code>@interface QDImageObject : NSObject <QDMessageObject>
/**
* 图片实例对象初始化方法
*
* @param image 要发送的图片
* @return 图片选项
*/
- (instancetype)initWithImage:(UIImage *)image;
/**
* 图片实例对象初始化方法
*
* @param image 要发送的图片
* @param imageOption 图片选项
* @return 图片实例对象
*/
- (instancetype)initWithImage:(UIImage *)image imageOption:(QDImageOption * _Nullable)imageOption;
/**
* 图片实例对象初始化方法
*
* @param filepath 要发送的图片路径
* @return 图片实例对象
* @discussion 使用此方法上传是不做压缩转换的原图上传
*/
- (instancetype)initWithSourcePath:(NSString *)filepath;
/**
* 展示名
*/
@property (nullable, nonatomic, copy) NSString *fileName;
/**
* 图片guid
*/
@property (nullable, nonatomic, copy, readonly) NSString *guid;
/**
* 图片尺寸
*/
@property (nonatomic, assign, readonly) CGSize size;
/**
* 图片本地路径
* @discussion 目前 SDK 没有提供下载大图的方法,但推荐使用这个地址作为图片下载地址
*/
@property (nullable, nonatomic, copy, readonly) NSString *path;
/**
* 本地缩略图路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *thumbPath;
/**
* 图片远程路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *url;
/**
* 略缩图远程路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *thumbUrl;
/**
* 图片选项
* @discussion 仅在发送时且通过 initWithImage: 方式初始化才有效
*/
@property (nullable, nonatomic ,strong) QDImageOption *option;
/**
* 文件大小
*/
@property (nonatomic, assign, readonly) long long fileLength;
/**
* 图片MD5
*/
@property (nullable,nonatomic, copy, readonly) NSString *md5;
@end</code></pre>
<p>参数列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">path</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">图片本地路径,目前 SDK 没有提供下载大图的方法,但推荐使用这个地址作为图片下载地址, APP 可以使用自己的下载类或者 SDWebImage 做图片的下载和管理</td>
</tr>
<tr>
<td style="text-align: center;">thumbPath</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">缩略图本地路径,缩略图在默认情况下由 SDK 自动下载,如果发现本地不存在缩略图,可手动调用 QDIMChatManager 协议中的获取缩略图方法 fetchMessageAttachment:error: 进行下载</td>
</tr>
<tr>
<td style="text-align: center;">url</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">大图的远程 URL 路径,开发者可通过这个属性自行下载大图</td>
</tr>
<tr>
<td style="text-align: center;">thumbUrl</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">缩略图远程 URL 路径,仅适用于使用SDK上传服务进行上传的资源,否则无效</td>
</tr>
<tr>
<td style="text-align: center;">size</td>
<td style="text-align: center;">CGSize</td>
<td style="text-align: center;">图片尺寸</td>
</tr>
<tr>
<td style="text-align: center;">option</td>
<td style="text-align: center;">QDImageOption</td>
<td style="text-align: center;">图片的压缩选项仅在发送时且通过 initWithImage: 方式初始化才有效</td>
</tr>
<tr>
<td style="text-align: center;">fieLength</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件大小</td>
</tr>
<tr>
<td style="text-align: center;">md5</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">图片MD5</td>
</tr>
</tbody>
</table>
<p>QDImageOption 图片选项参数列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">compressQuality</td>
<td style="text-align: center;">float</td>
<td style="text-align: center;">压缩参数默认为 0.5 ,可传入 0.0 - 1.0 的值,如果值为 0 或者不合法参数时按照 0.5 进行压缩</td>
</tr>
<tr>
<td style="text-align: center;">format</td>
<td style="text-align: center;">QDImageFormat</td>
<td style="text-align: center;">图片压缩格式,可选 JPEG 和 PNG 两种。默认为 JPEG</td>
</tr>
</tbody>
</table>
<p>以发送一条图片消息, 数据被 image 引用, 至好友 Id 为 user 的业务场景进行示例:</p>
<pre><code>// 构造出具体会话
QDSession *session = [QDSession session:@"user" type:QDSessionTypeP2P];
// 获得图片附件对象
QDImageObject *object = [[QDImageObject alloc] initWithImage:image];
// 构造出具体消息并注入附件
QDMessage *message = [[QDMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[QDClient sharedClient].chatManager sendMessage:message toSession:session error:&error];</code></pre>
<p>以发送一条图片消息, 数据在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:</p>
<pre><code>// 构造出具体会话
QDSession *session = [QDSession session:@"user" type:QDSessionTypeP2P];
// 获得图片附件对象
QDImageObject *object = [[QDImageObject alloc] initWithSourcePath:path];
// 构造出具体消息并注入附件
QDMessage *message = [[QDMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[QDClient sharedClient].chatManager sendMessage:message toSession:session error:&error];</code></pre>
<p>3 音频消息</p>
<p>附件原型:</p>
<pre><code>@interface QDAudioObject : NSObject <QDMessageObject>
/**
* 文件展示名
*/
@property (nullable, nonatomic, copy) NSString *fileName;
/**
* 声音文件的 guid
*/
@property (nullable, nonatomic, copy, readonly) NSString *guid;
/**
* 语音的本地路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *path;
/**
* 语音的远程路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *url;
/**
* 文件大小
*/
@property (nonatomic, assign, readonly) long long fileLength;
/**
* 语音时长,毫秒为单位
*/
@property (nonatomic, assign) long long duration;
/**
* 语音对象初始化方法
*
* @param sourcePath 语音路径
* @return 语音实例对象
*/
- (instancetype)initWithSourcePath:(NSString *)sourcePath;
@end</code></pre>
<p>参数列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">fileName</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件展示名</td>
</tr>
<tr>
<td style="text-align: center;">guid</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件在服务端的存储id</td>
</tr>
<tr>
<td style="text-align: center;">path</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">语音本地路径,语音在默认情况下由 SDK 自动下载,如果发现本地不存在语音文件,可手动调用 QDIMChatManager 协议中的获取语音附件方法 fetchMessageAttachment:error: 进行下载</td>
</tr>
<tr>
<td style="text-align: center;">url</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">语音的远程 URL 路径</td>
</tr>
<tr>
<td style="text-align: center;">duration</td>
<td style="text-align: center;">long long</td>
<td style="text-align: center;">语音时长,毫秒为单位</td>
</tr>
<tr>
<td style="text-align: center;">fileLength</td>
<td style="text-align: center;">long long</td>
<td style="text-align: center;">语音文件大小</td>
</tr>
</tbody>
</table>
<p>提供一种初始化</p>
<pre><code>/**
* 语音对象初始化方法
*
* @param sourcePath 语音路径
* @return 语音实例对象
*/
- (instancetype)initWithSourcePath:(NSString *)sourcePath;</code></pre>
<p>以发送一条语音消息, 语音保存在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:</p>
<pre><code>// 构造出具体会话
QDSession *session = [QDSession session:@"user" type:QDSessionTypeP2P];
// 获得语音附件对象
QDAudioObject *object = [[QDAudioObject alloc] initWithSourcePath:path];
// 构造出具体消息并注入附件
QDMessage *message = [[QDMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[QDClient sharedClient].chatManager sendMessage:message toSession:session error:&error];</code></pre>
<p>4 视频消息</p>
<p>附件原型:</p>
<pre><code>@interface QDVideoObject : NSObject <QDMessageObject>
/**
* 小视频实例对象初始化方法
*
* @param filepath 要发送的视频路径
* @return 小视频实例对象
*/
- (instancetype )initWithSourcePath:(NSString *)filepath;
/**
* 文件展示名
*/
@property (nullable, nonatomic, copy) NSString *fileName;
/**
* 小视频的guid
*/
@property (nullable, nonatomic, copy, readonly) NSString *guid;
/**
* 视频MD5
*/
@property (nullable, nonatomic, copy, readonly) NSString *md5;
/**
* 本地路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *path;
/**
* 远程路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *url;
/**
* 视频封面的远程路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *coverUrl;
/**
* 视频封面的本地路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *coverPath;
/**
* 封面尺寸
*/
@property (nonatomic, assign, readonly) CGSize coverSize;
/**
* 文件大小
*/
@property (nonatomic, assign, readonly) long long fileLength;
@end</code></pre>
<p>参数列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">fileName</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件展示名</td>
</tr>
<tr>
<td style="text-align: center;">guid</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件在服务端的存储id</td>
</tr>
<tr>
<td style="text-align: center;">path</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">视频的本地路径。目前 SDK 并不提供视频下载功能,但是建议 APP 使用这个 path 作为视频的下载地址,以便后期 SDK 提供缓存清理等功能</td>
</tr>
<tr>
<td style="text-align: center;">url</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">视频的远程路径</td>
</tr>
<tr>
<td style="text-align: center;">fileLength</td>
<td style="text-align: center;">long long</td>
<td style="text-align: center;">视频文件大小</td>
</tr>
<tr>
<td style="text-align: center;">md5</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">根据视频生成的MD5</td>
</tr>
<tr>
<td style="text-align: center;">coverUrl</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">视频封面的远程路径</td>
</tr>
<tr>
<td style="text-align: center;">coverPath</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">视频封面的本地路径。视频封面在默认情况下由 SDK 自动下载,如果发现本地不存在封面文件,可手动调用 QDChatManager 协议中的获取封面方法 fetchMessageAttachment:error: 进行下载</td>
</tr>
<tr>
<td style="text-align: center;">coverSize</td>
<td style="text-align: center;">CGSize</td>
<td style="text-align: center;">视频封面的大小,由 SDK 自行计算</td>
</tr>
</tbody>
</table>
<p>以路径初始化<br />
原型</p>
<pre><code>@interface QDVideoObject : NSObject <QDMessageObject>
/**
* 小视频实例对象初始化方法
*
* @param filepath 要发送的视频路径
* @return 小视频实例对象
*/
- (instancetype )initWithSourcePath:(NSString *)filepath;
@end</code></pre>
<p>以发送一条视频消息, 视频保存在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:</p>
<pre><code>// 构造出具体会话
QDSession *session = [QDSession session:@"user" type:QDSessionTypeP2P];
// 获得视频附件对象
QDVideoObject *object = [[QDVideoObject alloc] initWithSourcePath:path];
// 构造出具体消息并注入附件
QDMessage *message = [[QDMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[QDClient sharedClient].chatManager sendMessage:message toSession:session error:&error];</code></pre>
<p>5 文件消息<br />
附件原型:</p>
<pre><code>/**
* 文件实例对象
*/
@interface QDFileObject : NSObject <QDMessageObject>
/**
* 文件对象初始化方法(根据文件路径)
*
* @param sourcePath 文件路径
* @return 文件实例对象
*/
- (instancetype)initWithSourcePath:(NSString *)sourcePath;
/**
* 文件对象初始化方法(根据文件数据)
*
* @param data 文件数据
* @param extension 文件拓展名
* @return 文件实例对象
*/
- (instancetype)initWithData:(NSData *)data extension:(NSString *)extension;
/**
* 文件显示名
*/
@property (nullable, nonatomic, copy) NSString *fileName;
/**
* 文件Id
*/
@property (nullable, nonatomic, copy, readonly) NSString *guid;
/**
* 文件的本地路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *path;
/**
* 文件的远程路径
*/
@property (nullable, nonatomic, copy, readonly) NSString *url;
/**
* 文件MD5
*/
@property (nullable, nonatomic, copy, readonly) NSString *md5;
/**
* 文件大小
*/
@property (nonatomic, assign, readonly) long long fileLength;
@end</code></pre>
<p>参数列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">fileName</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件展示名</td>
</tr>
<tr>
<td style="text-align: center;">guid</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件在服务端的存储id</td>
</tr>
<tr>
<td style="text-align: center;">path</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件的本地路径</td>
</tr>
<tr>
<td style="text-align: center;">url</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">文件的远程路径</td>
</tr>
<tr>
<td style="text-align: center;">fileLength</td>
<td style="text-align: center;">long long</td>
<td style="text-align: center;">文件大小</td>
</tr>
<tr>
<td style="text-align: center;">md5</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">根据文件生成的MD5</td>
</tr>
</tbody>
</table>
<p>文件消息附件初始化提供两种方式:</p>
<p>以发送一条文件消息, 文件保存在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:</p>
<pre><code>// 构造出具体会话
QDSession *session = [QDSession session:@"user" type:QDSessionTypeP2P];
// 获得文件附件对象
QDFileObject *object = [[QDFileObject alloc] initWithSourcePath:path];
// 构造出具体消息并注入附件
QDMessage *message = [[QDMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[QDClient sharedClient].chatManager sendMessage:message toSession:session error:&error];</code></pre>
<p>以发送一条文件消息, 文件数据被 data 引用, 至好友 Id 为 user 的业务场景进行示例:</p>
<pre><code>// 构造出具体会话
QDSession *session = [QDSession session:@"user" type:QDSessionTypeP2P];
// 获得文件附件对象
QDFileObject *object = [[QDFileObject alloc] initWithData:data extension:@"data"];
// 构造出具体消息并注入附件
QDMessage *message = [[QDMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[QDClient sharedClient].chatManager sendMessage:message toSession:session error:&error];</code></pre>
<p>6 位置消息<br />
附件原型:</p>
<pre><code>@interface QDLocationObject : NSObject <QDMessageObject>
/**
纬度
*/
@property (nonatomic, assign, readonly) double latitude;
/**
经度
*/
@property (nonatomic, assign, readonly) double longitude;
/**
标题
*/
@property (nullable, nonatomic, copy, readonly) NSString *title;
/**
地理位置描述
*/
@property (nullable, nonatomic, copy, readonly) NSString *info;
/**
位置实例对象初始化方法
@param latitude 纬度
@param longitude 经度
@param title 标题
@param info 地理位置描述
@return 位置实例对象
*/
- (instancetype)initWithLatitude:(double)latitude longitude:(double)longitude title:(nullable NSString *)title info:(nullable NSString *)info;
@end</code></pre>
<p>参数列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">latitude</td>
<td style="text-align: center;">double</td>
<td style="text-align: center;">维度位置,由初始化时传入</td>
</tr>
<tr>
<td style="text-align: center;">longitude</td>
<td style="text-align: center;">double</td>
<td style="text-align: center;">维度位置,由初始化时传入</td>
</tr>
<tr>
<td style="text-align: center;">title</td>
<td style="text-align: center;">NSString</td>
<td style="text-align: center;">位置标题信息,由初始化时传入</td>
</tr>
<tr>
<td style="text-align: center;">info</td>
<td style="text-align: center;">long long</td>
<td style="text-align: center;">位置详情信息,由初始化时传入</td>
</tr>
</tbody>
</table>
<p>以发送一条位置消息, 经纬度为 (48.28476,120.94720) ,地点名为 address , 至好友 Id 为 user 的业务场景进行示例:</p>
<pre><code>// 构造出具体会话
QDSession *session = [QDSession session:@"user" type:QDSessionTypeP2P];
// 获得位置附件对象
QDLocationObject *object = [[QDLocationObject alloc] initWithLatitude:120.94720
longitude:48.28476
title:@"title"
info:@"address"];
// 构造出具体消息并注入附件
QDMessage *message = [[QDMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[QDClient sharedClient].chatManager sendMessage:message toSession:session error:&error];</code></pre>
<p>7 通知消息</p>
<p>一些特定场景的行为,服务器预置了一些通知消息。通知消息也是一种特定消息,开发者需要解析消息中附带的信息,来获取通知内容。</p>
<p>附件原型:</p>
<pre><code>@interface QDNotificationObject : NSObject <QDMessageObject>
/**
* 通知内容
*/
@property (nonatomic, strong, readonly) QDNotificationContent *content;
/**
* 通知类型
*/
@property (nonatomic, assign, readonly) QDNotificationType notificationType;
@end</code></pre>
<table>
<thead>
<tr>
<th style="text-align: center;">参数列表</th>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">content</td>
<td style="text-align: center;">QDNotificationContent</td>
<td style="text-align: center;">通知内容</td>
</tr>
<tr>
<td style="text-align: center;">notificationType</td>
<td style="text-align: center;">QDNotificationType</td>
<td style="text-align: center;">通知类型,通知类型会随着 SDK 版本升级扩展,开发者需要考虑升级所带来的兼容问题</td>
</tr>
</tbody>
</table>
<h2>接收消息</h2>
<p>接收消息过程通过 chatManager 的回调函数通知上层</p>
<p>原型</p>
<pre><code>@protocol QDChatManagerDelegate <NSObject>
/**
* 收到消息回调
*
* @param messages 消息列表,内部为QDMessage
*/
- (void)onRecvMessages:(NSArray<QDMessage *> *)messages;
@end</code></pre>
<p>参数列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">messages</td>
<td style="text-align: center;">NSArray</td>
<td style="text-align: center;">消息集合,集合按时间排序并保证所属同一个会话</td>
</tr>
</tbody>
</table>
<p>如果收到的是图片,视频等需要下载附件的消息,在回调的处理中还需要调用下载附件接口</p>
<p>原型</p>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
* 收取消息附件
*
* @param message 需要收取附件的消息
* @param error 错误
* @return 是否调用成功
* @discussion 附件包括:图片消息的图片缩略图,视频消息的视频缩略图,音频消息的音频文件,文件消息的文件以及自定义消息中的自定义文件
* 个人和群组消息 SDK 会在收到该消息时自动调用本接口,自动下载除 "文件消息的文件" 外的所有附件内容
*/
- (BOOL)fetchMessageAttachment:(QDMessage *)message error:(NSError * __nullable *)error;
@end</code></pre>
<p>进行附件的下载,附件的下载过程会通过回调反馈</p>
<pre><code>@protocol QDChatManagerDelegate <NSObject>
/**
* 收取消息附件回调
*
* @param message 当前收取的消息
* @param progress 进度 (0-1)
* @discussion 附件包括:图片,视频的缩略图,语音文件
*/
- (void)fetchMessageAttachment:(QDMessage *)message progress:(float)progress;
@end</code></pre>
<h2>已读回执</h2>
<p>在会话界面中调用发送已读回执的接口并传入最后一条消息,即表示这之前的消息都已读,对端将收到此回执。</p>
<p>发送已读回执</p>
<pre><code>@protocol QDChatManager <NSObject>
/**
* 发送已读消息
*
* @param message 已读消息
* @param completion 完成回调
*/
- (void)sendMessageReceipt:(QDMessage *)message completion:(void(^ _Nullable)(NSError * _Nullable error))completion;
@end</code></pre>
<p>接收已读回执</p>
<pre><code>@protocol QDChatManagerDelegate <NSObject>
/**
* 收到消息回执
*/
- (void)onRecvReceiptsMessage:(QDMessage *)message;
@end</code></pre>
<p>消息撤回</p>
<p>在会话时,允许用户撤回一定时间内发送过的消息。</p>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
* 撤回消息
*
* @param message 需要被撤回的消息
* @param completion 完成回调
*/
- (void)revokeMessage:(QDMessage *)message completion:(void(^ _Nullable)(NSError * _Nullable error))completion;</code></pre>
<p>在撤回消息请求调用成功后, SDK 会先回调给上层成功,再自动将本地的这条消息删除。如果需要在撤回后显示一条已撤回的提示 ( 见 Demo 交互 ) ,开发者可以自行构造一条提醒消息并插入本地数据库。</p>
<p>当有消息撤回发生时,被撤回方 SDK 会触发回调:</p>
<pre><code>@protocol QDChatManagerDelegate <NSObject>
/**
* 收到消息被撤回的通知
*
* @param notification 被撤回的消息信息
* @discusssion 云信在收到消息撤回后,会先从本地数据库中找到对应消息并进行删除,之后通知上层消息已删除
*/
- (void)onRecvRevokeMessageNotification:(QDRevokeMessageNotification *)notification;
@end</code></pre>
<p>SDK 在收到消息撤回后,会先从本地数据库中找到对应消息并进行删除,之后通知上层消息已删除。如果需要在撤回后显示一条已撤回的提示 ( 见 Demo 交互 ) ,开发者在这个回调中自行构造一条提醒消息并插入本地数据库。</p>