这两天在做环信的消息回撤,在网上找了许久没有这种案例,之后官方的一些方法,但是自己做,还是需要花点时间去整理,所以我决定等我把这个做好之后,分享给大家,如果做的不好多多指教,谢谢~
首先要实现消息撤回就是两个步骤,一个是发送要回撤的透传消息 。一个是接收透传信息,删除要回撤的消息。
第一步 : 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 ;
}
|
这样就好了,希望能帮到你们~