====== SDK 2.1.3 release note ====== ---- 强推更新SDK方式: setp1、将旧的sdk从工程中删除,导入新的sdk; setp2、编译工程,会出现一系列的error和warning; setp3、将error和warning逐个击破,千万不要忽略warning,亲~~。 ===== SDK目录讲解 ===== sdk文件夹中有三个子文件夹:include、lib、resources,请不要擅自修改这些文件夹的任何东西,下面依次介绍这三个子文件夹。 * lib 静态库,包含连个静态库libEaseMobClientSDK.a和libEaseMobClientSDKLite.a。libEaseMobClientSDKLite.a不包含实时语音功能,libEaseMobClientSDK.a包含所有功能。如果你的app中不需要实时语音功能,删掉libEaseMobClientSDK.a只使用libEaseMobClientSDKLite.a即可。 * resources sdk的bundle,包含旧版sdk的数据库、消息提示音,sdk配置文件。其中sdk配置文件已加密,旧版sdk数据库几乎没什么实质作用。 * include 包含sdk的头文件。 主要介绍下include,所有的接口都在这个文件夹中。 include目录讲解 * EaseMobClientSDK/EaseMobClientSDKLite 包含在项目中要引用的总头文件,即在代码中只需#import”EMSDKFull.h”或#import”EaseMob.h”即可调用所有对应的api。 * CallService 包含实时语音相关的接口 * ChatService 包含聊天相关的接口,比如注册、登录、退出、单聊、群聊、群组等 * Utility 包含DeviceManager和ErrorManager。DeviceManager硬件相关接口,ErrorManager错误码定义 注: 1、 include包含5个子文件夹:CallService、ChatService、EaseMobClientSDK、EaseMobClientSDKLite、Utility。如果无需实时语音功能,将CallService和EaseMobClientSDK删掉即可。 2、 类似EM@Manager命名格式的文件夹的内部结构都是相似的。delegates文件夹包含各种代理接口,internal文件夹包含各种协议的声明,types文件夹包含各种实例的声明。 ===== 注意事项 ===== 1、发送一个含多个附件的EMMessage, 附件包括图片/语音/视频/文件,正在优化; 2、转发或插入一条含附件的EMMessage, 附件包括图片/语音/视频/文件,不支持; 3、多附件下载或上传的进度回调,进度会不准; ===== 使用技巧 ===== - 不支持修改数据库中已存在的EMMessage的from属性,to属性,conversationChatter属性; - 如果想判断EMConversation里边有没有message,调用【EMConversation latestMessage】,千万不要调用【EMConversation loadAllMessages】,你的app会被拖死的; - 如果想判断EMMessage属于哪个EMConversation, 通过EMMessage.conversationChatter属性判断; - 2.1.2以前版本的ios sdk会出现conversation.chatter == nil的情况,2.1.2及以后版本对这个问题有修改,但是为了防止有漏网的,在调用【[EaseMob sharedInstance].chatManager conversationForChatter:chatter isGroup:_isChatGroup】前,判断一下chatter是否为空; - 其他端给ios客户端发消息时,要避免出现NSNULL类型,会造成崩溃,ios SDK目前没有容错NSNULL; - 2.1.2及以后版本,message列表要你们自己维护了,便于定制,也好内存管理; - 消息推送分两种情况:app死掉之后的是离线推送,环信负责;app在后台没死之前是本地推送,需要你们自己负责; - ios SDK中的接口,以async开头的是异步方法,其余为同步方法。 ===== bug fix ===== 1、发送消息回执失败,即客户端A调用方法【sendHasReadResponseForMessage:】,客户端B不会收到【didReceiveHasReadResponse:】回调。 使用2.1.2的补救办法: EMMessage *tmpMessage = [[EMMessage alloc] initMessageWithID:message.messageId sender:message.to receiver:message.from bodies:nil]; [[EaseMob sharedInstance].chatManager sendHasReadResponseForMessage:tmpMessage]; 正确方法:[[EaseMob sharedInstance].chatManager sendHasReadResponseForMessage:message]; 搜索关键词:sendHasReadResponseForMessage; 2、在不正确的操作流程下,conversation的消息未读数会出现-1,修复为最小是0,不会返回负数; 3、Database的数据存到了Document目录下,迁移到Library目录下; 4、特殊情况下,会出现收到离线消息的时候SDK中的Database还没有open, 造成第一条离线消息无法存进去; ===== SDK内部细节调整 ===== 1、登录 分为自动登录和手动登录。 a>、手动登录是调用sdk的login相关接口; b>、登录成功之后,(一定是在登录成功之后)设置【EMChatManager setIsAutoLoginEnabled:YES】即设置为自动登录,下次启动之后,判断【EMChatManager isAutoLoginEnabled】是否==YES,等于YES,就不要再去手动登录,sdk内部会自动进行登录,你只需监听【willAutoLoginWithInfo:error:】和【didAutoLoginWithInfo:error:】。sdk自动登录在sdk接口【application:didFinishLaunchingWithOptions:】中实现,所以确定该方法在你的工程代码的AppDelegate类中有调用。 2、离线消息 分为离线cmd消息和离线非cmd消息两种类型。开始监听的方法是同一个【willReceiveOfflineMessages】;在离线消息接收过程中,不会返回回调【didReceive(Cmd)Message:】和【didUnreadMessagesCountChanged】;结束后返回的回调有三个【didFinishedReceiveOfflineMessages:】、【didFinishedReceiveOfflineCmdMessages:】和【didUnreadMessagesCountChanged】(如果没有离线消息,不返回)。 3、群成员被踢 是这样的流程:踢在线的,对方会收到回调【group:didLeave:error:】;踢不在线的,对方上线后不会收到回调;但是两种情况群都会被移除。 4、EMMessage 因为Android SDK暂时不支持多body,为了统一,IOS SDK请暂时不要使用多body的EMMessage结构。 ===== SDK性能优化 ===== 1、网络状态不好时,会导致频繁掉线、重连,在这个过程中,程序会卡; 新功能大放送 1、点对点语音通话bate版,目前只支持wifi非relay情况下使用。如果想在黑屏状态下能继续通话,请选择VIOP。 ===== new api ===== EMReceipt /*! @property @brief 回执所属的对话对象的chatter */ @property (strong, nonatomic) NSString *conversationChatter; 添加理由:便于判断收到的回执是哪个conversation的。 ===== change api ===== IChatManagerLogin 修改理由:当前登录账号被踢或者被删除,只需要在客户端断开Socket,不需要解除device token的绑定 1、/*! @method @brief 注销当前登录用户 @discussion 当接收到【didLoginFromOtherDevice】和【didRemovedFromServer】的回调时,调用此方法,isUnbind传NO @param isUnbind 是否解除device token @param pError 错误信息 @result 返回注销信息 */ - (void)asyncLogoff EM_DEPRECATED_IOS(2_0_6, 2_1_1, "Use - asyncLogoffWithUnbindDeviceToken:"); - (NSDictionary *)logoffWithUnbindDeviceToken:(BOOL)isUnbind error:(EMError **)pError; 2、/*! @method @brief 异步方法, 注销当前登录用户 @discussion 当接收到【didLoginFromOtherDevice】和【didRemovedFromServer】的回调时,调用此方法,isUnbind传NO @result 完成后【didLogoffWithError:】回调会被触发. */ - (NSDictionary *)logoffWithError:(EMError **)pError EM_DEPRECATED_IOS(2_0_6, 2_1_1, "Use - logoffWithUnbindDeviceToken:error:"); - (void)asyncLogoffWithUnbindDeviceToken:(BOOL)isUnbind; 3、/*! @method @brief 异步方法, 注销当前登录用户 @discussion 当接收到【didLoginFromOtherDevice】和【didRemovedFromServer】的回调时,调用此方法,isUnbind传NO @param completion 回调 @param aQueue 回调时的线程 @result */ - (void)asyncLogoffWithCompletion:(void (^)(NSDictionary *info, EMError *error))completion onQueue:(dispatch_queue_t)aQueue EM_DEPRECATED_IOS(2_0_6, 2_1_1, "Use - asyncLogoffWithUnbindDeviceToken:completion:onQueue:"); - (void)asyncLogoffWithUnbindDeviceToken:(BOOL)isUnbind completion:(void (^)(NSDictionary *info, EMError *error))completion onQueue:(dispatch_queue_t)aQueue; IChatManagerConversation 修改理由:以下方法由开发者传入append2Chat参数决定是否返回回调方法,便于开发者自定义。不带append2Chat参数的对应方法,默认不返回回调方法,注释中有详细描述 1、/*! @method @brief 获取当前登录用户的会话列表 @param append2Chat 是否返回相关回调方法 @result 会话对象列表 */ - (NSArray *)loadAllConversationsFromDatabase EM_DEPRECATED_IOS(2_1_0, 2_1_2, "Use - loadAllConversationsFromDatabaseWithAppend2Chat:"); - (NSArray *)loadAllConversationsFromDatabaseWithAppend2Chat:(BOOL)append2Chat; 2、/*! @method @brief 删除某个会话对象 @discussion @param chatter 这个会话对象所对应的用户名 @param aDeleteMessages 是否删除这个会话对象所关联的聊天记录 @param append2Chat 是否返回相关回调方法 @result 删除成功或失败 */ - (BOOL)removeConversationByChatter:(NSString *)chatter deleteMessages:(BOOL)aDeleteMessages EM_DEPRECATED_IOS(2_1_0, 2_1_2, "Use - removeConversationByChatter:deleteMessages:append2Chat:"); - (BOOL)removeConversationByChatter:(NSString *)chatter deleteMessages:(BOOL)aDeleteMessages append2Chat:(BOOL)append2Chat; 3、/*! @method @brief 删除某几个会话对象 @discussion @param chatters 这几个要被删除的会话对象所对应的用户名列表 @param aDeleteMessages 是否删除这个会话对象所关联的聊天记录 @param append2Chat 是否返回相关回调方法 @result 成功删除的会话对象的个数 */ - (NSUInteger)removeConversationsByChatters:(NSArray *)chatters deleteMessages:(BOOL)aDeleteMessages EM_DEPRECATED_IOS(2_1_0, 2_1_2, "Use - removeConversationsByChatters:deleteMessages:append2Chat:"); - (NSUInteger)removeConversationsByChatters:(NSArray *)chatters deleteMessages:(BOOL)aDeleteMessages append2Chat:(BOOL)append2Chat; 4、/*! @method @brief 删除所有会话对象 @discussion @param aDeleteMessages 是否删除这个会话对象所关联的聊天记录 @param append2Chat 是否返回相关回调方法 @result 是否成功执行 */ - (BOOL)removeAllConversationsWithDeleteMessages:(BOOL)aDeleteMessages EM_DEPRECATED_IOS(2_1_0, 2_1_2, "Use - removeAllConversationsWithDeleteMessages:append2Chat:"); - (BOOL)removeAllConversationsWithDeleteMessages:(BOOL)aDeleteMessages append2Chat:(BOOL)append2Chat; IChatManagerGroup 修改理由:以下方法由开发者传入append2Chat参数决定是否返回回调方法,便于开发者自定义。不带append2Chat参数的对应方法,默认不返回回调方法,注释中有详细描述 /*! @method @brief 从数据库获取与登录者相关的群组 @param append2Chat 是否返回相关回调方法 @return 错误信息 */ - (NSArray *)loadAllMyGroupsFromDatabase EM_DEPRECATED_IOS(2_1_0, 2_1_2, "Use - loadAllMyGroupsFromDatabaseWithAppend2Chat:"); - (NSArray *)loadAllMyGroupsFromDatabaseWithAppend2Chat:(BOOL)append2Chat; IEMChatProgressDelegate /*! @method @brief 设置进度 @discussion 用户需实现此接口用以支持进度显示 @param progress 值域为0到1.0的浮点数 @param message 某一条消息的progress @param messageBody 某一条消息某个body的progress @result */ - (void)setProgress:(float)progress forMessage:(EMMessage *)message EM_DEPRECATED_IOS(2_0_6, 2_1_2, "Use - setProgress:forMessage:forMessageBody:"); - (void)setProgress:(float)progress forMessage:(EMMessage *)message forMessageBody:(id)messageBody;