这两天在做环信的消息回撤,在网上找了许久没有这种案例,之后官方的一些方法,但是自己做,还是需要花点时间去整理,所以我决定等我把这个做好之后,分享给大家,如果做的不好多多指教,谢谢~

首先要实现消息撤回就是两个步骤,一个是发送要回撤的透传消息 。一个是接收透传信息,删除要回撤的消息。

第一步 : ChatViewController.m 自己定义一个

UIMenuItem *_messageRetracementMenuItem;

第二步

这个方法里面添加一下撤回字段,我把整段都复制过来了,你们对一下

- (void)showMenuViewController:(UIView *)showInView

andIndexPath:(NSIndexPath *)indexPath

messageType:(EMMessageBodyType)messageType

{

if (self.menuController == nil) {

self.menuController = [UIMenuController sharedMenuController];

}

if (_deleteMenuItem == nil) {

_deleteMenuItem = [[UIMenuItem alloc] initWithTitle:@"删除" action:@selector(deleteMenuAction:)];

}

if (_copyMenuItem == nil) {

_copyMenuItem = [[UIMenuItem alloc] initWithTitle:@"复制" action:@selector(copyMenuAction:)];

}

if (_transpondMenuItem == nil) {

_transpondMenuItem = [[UIMenuItem alloc] initWithTitle:@"转发" action:@selector(transpondMenuAction:)];

}

if (_messageRetracementMenuItem == nil) {

_messageRetracementMenuItem = [[UIMenuItem alloc] initWithTitle:@"撤回" action:@selector(messageRetracementMenuAction:)];

}

NSString *loginUsername =  [[EMClient sharedClient] currentUsername];

id<IMessageModel> model = [self.dataArray objectAtIndex:self.menuIndexPath.row];

if (messageType == EMMessageBodyTypeText) {

if ([loginUsername isEqualToString:model.message.from]) {

[self.menuController setMenuItems:@[_copyMenuItem, _deleteMenuItem,_transpondMenuItem,_messageRetracementMenuItem]];

} else {

[self.menuController setMenuItems:@[_copyMenuItem, _deleteMenuItem,_transpondMenuItem]];

}

} else if (messageType == EMMessageBodyTypeImage){

if ([loginUsername isEqualToString:model.message.from]) {

[self.menuController setMenuItems:@[_deleteMenuItem,_transpondMenuItem,_messageRetracementMenuItem]];

} else {

[self.menuController setMenuItems:@[_deleteMenuItem,_transpondMenuItem]];

}

} else {

if ([loginUsername isEqualToString:model.message.from]) {

[self.menuController setMenuItems:@[_deleteMenuItem,_messageRetracementMenuItem]];

} else {

[self.menuController setMenuItems:@[_deleteMenuItem]];

}

}

[self.menuController setTargetRect:showInView.frame inView:showInView.superview];

[self.menuController setMenuVisible:YES animated:YES];

}

第三步:实现这个回撤的方法 ,我这边做的是在两分钟内撤回,超过两分钟提示

- (void)messageRetracementMenuAction:(id)sender {

if (self.menuIndexPath && self.menuIndexPath.row > 0) {

id<IMessageModel> model = [self.dataArray objectAtIndex:self.menuIndexPath.row];

NSString *messageId  = model.message.messageId;

// 发送这条消息在服务器的时间戳

NSTimeInterval time1 = (model.message.serverTime) / 1000.0;

// 当前的时间戳

NSTimeInterval nowTime = [[NSDate date] timeIntervalSince1970];

NSTimeInterval cha = nowTime - time1;

NSInteger timecha = cha;

if (timecha <= 120) {

[self revokeMessageWithMessageId:messageId conversationId:self.conversation.conversationId];

} else {

[self showHint:@"消息已经超过两分钟 无法撤回"];

}

}

}

//  你撤回之后会发现你消息撤回了,但是还在,但是你要重新运行一下撤回的消息就会没有,所以就是有一步当你撤回的时候,还要手动删除一下。

主要删除 self.conversation,self.dataArray,self.messsagesSource,这三个,然后刷新一下。

其中  REVOKE_FLAG 和 msgId 一定要和安卓对应,两边要写一样的,要不然另一方撤回这边是接收不到的或者你这边撤回另一方收不到。

还有 message.chatType 也要注意,如果你做的不只单聊,那就要判断一下,我上面代码有些,一个群聊,一个单聊。

// 发送回撤的透传消息

- (void)revokeMessageWithMessageId:(NSString *)aMessageId

conversationId:(NSString *)conversationId {

EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:@"REVOKE_FLAG"];

NSDictionary *ext = @{@"msgId":aMessageId};

NSString *currentUsername = [EMClient sharedClient].currentUsername;

EMMessage *message = [[EMMessage alloc] initWithConversationID:conversationId from:currentUsername  to:conversationId body:body ext:ext];

if (self.conversation.type == EMConversationTypeGroupChat){

message.chatType = EMChatTypeGroupChat;

} else {

message.chatType = EMChatTypeChat;

}

//发送cmd消息

[[EMClient sharedClient].chatManager asyncSendMessage:message progress:nil completion:^(EMMessage *message, EMError *error) {

if (!error) {

NSLog(@"发送成功");

// 需要自己从dataArray里将聊天消息删掉, 还有self.conversation里,最后刷新

NSMutableIndexSet *indexs = [NSMutableIndexSet indexSetWithIndex:self.menuIndexPath.row];

NSMutableArray *indexPaths = [NSMutableArray arrayWithObjects:self.menuIndexPath, nil];

[self.conversation deleteMessageWithId:aMessageId];

[self.messsagesSource removeObject:message];

if (self.menuIndexPath.row - 1 >= 0) {

id nextMessage = nil;

id prevMessage = [self.dataArray objectAtIndex:(self.menuIndexPath.row - 1)];

if (self.menuIndexPath.row + 1 < [self.dataArray count]) {

nextMessage = [self.dataArray objectAtIndex:(self.menuIndexPath.row + 1)];

}

if ((!nextMessage || [nextMessage isKindOfClass:[NSString class]]) && [prevMessage isKindOfClass:[NSString class]]) {

[indexs addIndex:self.menuIndexPath.row - 1];

[indexPaths addObject:[NSIndexPath indexPathForRow:(self.menuIndexPath.row - 1) inSection:0]];

}

}

[self.dataArray removeObjectsAtIndexes:indexs];

[self.tableView beginUpdates];

[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];

[self.tableView endUpdates];

if ([self.dataArray count] == 0) {

self.messageTimeIntervalTag = -1;

}

}  else {

NSLog(@"发送失败");

}

}];

}

第四步:在你接收消息  - (void)didReceiveMessages:(NSArray *)aMessages 这个方法的控制器里 ChatDemoHelper.h  添加接收透传消息的方法,

接收透传消息是环信系统自带的方法。我这边还有一个没做好,就是别人撤回后在当前聊天界面的刷新没刷新好,你们自己做一下。

1 // 接收透传消息

2 - (void)didReceiveCmdMessages:(NSArray *)aCmdMessages {

3     BOOL isRefreshCons = YES;

4     for (EMMessage *cmdMessage in aCmdMessages) {

5         EMCmdMessageBody *body = (EMCmdMessageBody *)cmdMessage.body;

6         if ([body.action isEqualToString:@"REVOKE_FLAG"]) {

7             NSString *revokeMessageId = cmdMessage.ext[@"msgId"];

8             BOOL isSuccess = [self removeRevokeMessageWithChatter:cmdMessage.conversationId conversationType:(EMConversationType)cmdMessage.chatType messageId:revokeMessageId];

9             if (isSuccess)  {

10                 if (_chatVC == nil) {

11                     _chatVC = [self _getCurrentChatView];

12               }

13                 BOOL isChatting = NO;

14                 if (_chatVC)  {

15                      isChatting = [cmdMessage.conversationId isEqualToString:_chatVC.conversation.conversationId];

16                 }

17                 if (_chatVC == nil || !isChatting) {

18                     [self _handleReceivedAtMessage:cmdMessage];

19                     if (self.conversationListVC) {

20                         [[NSNotificationCenter defaultCenter] postNotificationName:@"conversationListRefresh" object:nil];

21                     }

22                     if (self.mainVC) {

23                         [[NSNotificationCenter defaultCenter] postNotificationName:@"conversationListRefresh" object:nil];

24                         [self.mainVC setupUnreadMessageCount];

25                     }

26                     return;

27                 }

28                 if (isChatting) {

29                     isRefreshCons = NO;

30               }

31                 if (isRefreshCons) {

32                     if (self.conversationListVC) {

33                         [[NSNotificationCenter defaultCenter] postNotificationName:@"conversationListRefresh" object:nil];

34                     }

35                     if (self.contactViewVC) {

36                         [[NSNotificationCenter defaultCenter] postNotificationName:@"setupUnreadMessageCount" object:nil];

37                     }

38                 }

39             }  else {

40                 NSLog(@"接收失败");

41             }

42         }

43     }

44 }

1 // 删除消息

2 - (BOOL)removeRevokeMessageWithChatter:(NSString *)aChatter

3                       conversationType:(EMConversationType)type

4                              messageId:(NSString *)messageId{

5

6     EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:aChatter type:type createIfNotExist:YES];

7     [conversation deleteMessageWithId:messageId];

8     return YES;

9 }

这样就好了,希望能帮到你们~

iOS 环信消息撤回的更多相关文章

  1. iOS 环信透传cmd消息多次重复接收,解决办法

    由于项目需求,需要在项目中接到消息的时候做不同界面的不同的操作,哪儿需要哪儿就要添加代理:引起代理事件重复执行:所以要在VC显示的时候添加代理,消失的时候删除代理 环信 透传 消息多次接收情况(由于代 ...

  2. 集成IOS 环信SDK

    集成IOS SDK 在您阅读此文档时,我们假定您已经具备了基础的 iOS 应用开发经验,并能够理解相关基础概念. 下载SDK 通过Cocoapods下载地址 不包含实时语音版本SDK(EaseMobC ...

  3. iOS 环信集成项目应用

    环信iOS端3.0版本集成记录--聊天界面篇 环信离线推送证书... 1,环信处在后台的时候,消息的接收与推送 离线发推送 配置属性 EMCallOptions *options = [[EMClie ...

  4. iOS: 环信的推送

    原文:http://m.blog.csdn.net/article/details?id=38824551 1.先创建一个apns证书,链接如下 http://developer.easemob.co ...

  5. iOS 环信集成问题(连文档都不说明的坑。。)

    首先,关于环信SDK的下载和一些依赖库的添加,在此我就不做详细介绍,(http://www.easemob.com/download/im)附上环信官网文档,可以看一下,上面都可以下载,也有相关配置介 ...

  6. iOS 环信集成单聊界面,出现消息重复问题

    解决办法很简单,数据重复就是EaseMessageViewController和ChatViewController重复调用了这个吧?//通过会话管理者获取收发消息 [self tableViewDi ...

  7. [Java]直播方案----[接入环信聊天室]+[腾讯云直播]

    辛辛苦苦写的,转载请注明一下,这点信任我想还是有的吧,谢谢了. http://www.cnblogs.com/applerosa/p/7162268.html 之前做了直播,一直没时间写,好不容易闲下 ...

  8. 李洪强iOS开发之-环信04_消息

    李洪强iOS开发之-环信04_消息 消息:IM 交互实体,在 SDK 中对应的类型是 EMMessage.EMMessage 由 EMMessageBody 组成. 构造消息   构造文字消息 EMT ...

  9. 李洪强iOS开发之-环信05_EaseUI 使用指南

    李洪强iOS开发之-环信05_EaseUI 使用指南 EaseUI 使用指南 简介 EaseUI 封装了 IM 功能常用的控件(如聊天会话.会话列表.联系人列表).旨在帮助开发者快速集成环信 SDK. ...

随机推荐

  1. Android---Parcelable包装类的作用

    android提供了一种新的类型:Parcel.本类被用作封装数据的容器,封装后的数据可以通过Intent或IPC传递. 除了基本类型以外,只有实现了Parcelable接口的类才能被放入Parcel ...

  2. CodeForces 606B Testing Robots

    模拟,题意看了一小时 /* *********************************************** Author :Zhou Zhentao Email :774388357@ ...

  3. Java中的局部内部类

    package Smoke; public class Inner { private int num = 3; class Limian{ public void show(){ //内部类可以访问 ...

  4. DML、DDL、DCL区别及介绍

    DML(data manipulation language):        它们是SELECT.UPDATE.INSERT.DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作 ...

  5. tls session resumption

    http://stackoverflow.com/questions/12318325/resume-tls-connection-in-java As long as you use the sam ...

  6. FastCgi与Cgi

      转载请注明出处:http://www.cnblogs.com/stonehat/p/6286966.html  他们之间的不同在于   FastCgi的进程是常驻的,监听一个socket, 无线循 ...

  7. XML&AJAX

    AJAX: Asynchronous Javascript and XML 1. 客户端触发异步操作 2. 创建新的XMLHttpRequest, 是重要的js对象,通过它提起对服务器端的请求 3. ...

  8. iOS 添加导航按钮

    iOS设置导航按钮navigationBar中包含了这几个重要组成部分:leftBarButtonItem, rightBarButtonItem, backBarButtonItem, title. ...

  9. vim中c/c++源码跳转

    在使用vim阅读c/c++代码的时候,代码跳转很重要, 在学习redis代码的时候遇到这个问题. 网上查找之后通过实践发现cscope比较好用,可以很方便的实现跳转 1. 安装cscope sudo ...

  10. tp框架中的静态验证

    //制定命名空间在Home 模块下Model文件夹下 如:namespace Home\Model; //引用父类 如:use Think\Model; //实例化表 如:class ZhuCeMod ...