这两天在做环信的消息回撤,在网上找了许久没有这种案例,之后官方的一些方法,但是自己做,还是需要花点时间去整理,所以我决定等我把这个做好之后,分享给大家,如果做的不好多多指教,谢谢~
首先要实现消息撤回就是两个步骤,一个是发送要回撤的透传消息 。一个是接收透传信息,删除要回撤的消息。
第一步 : ChatViewController.m 自己定义一个
1
|
UIMenuItem *_messageRetracementMenuItem; |
第二步
这个方法里面添加一下撤回字段,我把整段都复制过来了,你们对一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
- ( 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 ]; } </imessagemodel> |
第三步:实现这个回撤的方法 ,我这边做的是在两分钟内撤回,超过两分钟提示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
- ( 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:@ "消息已经超过两分钟 无法撤回" ]; } } } </imessagemodel> |
// 你撤回之后会发现你消息撤回了,但是还在,但是你要重新运行一下撤回的消息就会没有,所以就是有一步当你撤回的时候,还要手动删除一下。
主要删除 self.conversation,self.dataArray,self.messsagesSource,这三个,然后刷新一下。
其中 REVOKE_FLAG 和 msgId 一定要和安卓对应,两边要写一样的,要不然另一方撤回这边是接收不到的或者你这边撤回另一方收不到。
还有 message.chatType 也要注意,如果你做的不只单聊,那就要判断一下,我下面代码有些,一个群聊,一个单聊。
// 发送回撤的透传消息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
- ( 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.m 添加接收透传消息的方法,
接收透传消息是环信系统自带的方法。我这边还有一个没做好,就是别人撤回后在当前聊天界面的刷新没刷新好,你们自己做一下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
1 // 接收透传消息 - ( void )didReceiveCmdMessages:( NSArray *)aCmdMessages { BOOL isRefreshCons = YES ; for (EMMessage *cmdMessage in aCmdMessages) { EMCmdMessageBody *body = (EMCmdMessageBody *)cmdMessage.body; if ([body.action isEqualToString:@ "REVOKE_FLAG" ]) { NSString *revokeMessageId = cmdMessage.ext[@ "msgId" ]; BOOL isSuccess = [ self removeRevokeMessageWithChatter:cmdMessage.conversationId conversationType:(EMConversationType)cmdMessage.chatType messageId:revokeMessageId]; if (isSuccess) { if (_chatVC == nil ) { _chatVC = [ self _getCurrentChatView]; } BOOL isChatting = NO ; if (_chatVC) { isChatting = [cmdMessage.conversationId isEqualToString:_chatVC.conversation.conversationId]; } if (_chatVC == nil || !isChatting) { [ self _handleReceivedAtMessage:cmdMessage]; if ( self .conversationListVC) { [[ NSNotificationCenter defaultCenter] postNotificationName:@ "conversationListRefresh" object: nil ]; } if ( self .mainVC) { [[ NSNotificationCenter defaultCenter] postNotificationName:@ "conversationListRefresh" object: nil ]; [ self .mainVC setupUnreadMessageCount]; } return ; } if (isChatting) { isRefreshCons = NO ; } if (isRefreshCons) { if ( self .conversationListVC) { [[ NSNotificationCenter defaultCenter] postNotificationName:@ "conversationListRefresh" object: nil ]; } if ( self .contactViewVC) { [[ NSNotificationCenter defaultCenter] postNotificationName:@ "setupUnreadMessageCount" object: nil ]; } } } else { NSLog (@ "接收失败" ); } } } } |
1 // 删除消息
1
2
3
4
5
6
7
8
|
- ( BOOL )removeRevokeMessageWithChatter:( NSString *)aChatter conversationType:(EMConversationType)type messageId:( NSString *)messageId{ EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:aChatter type:type createIfNotExist: YES ]; [conversation deleteMessageWithId:messageId]; return YES ; } |
这样就好了,希望能帮到你们~