如何处理MUC聊天消息 - 消息重复

时间:2014-10-31 18:35:37

标签: ios xmpp ejabberd xmppframework multiuserchat

我使用XMPP框架实现了一对一聊天它在一对一聊天中得到了广泛的支持。消息存档和提取非常简单。但我发现,处理群聊聊天消息很难保存和显示。排序和谓词都失败了。显示重复的消息。

这是我在获取已保存的消息之前加入房间的方式)

XMPPRoomCoreDataStorage *coreDataRoomStorage=[self appDelegate].xmppRoomCoreDataStorage;
XMPPRoom *room=[[XMPPRoom alloc]initWithRoomStorage:coreDataRoomStorage jid:user.bareJid];
    [room activate:[self appDelegate].xmppStream];
    [room addDelegate:[self appDelegate] delegateQueue:dispatch_get_main_queue()];
    [room joinRoomUsingNickname:user.user_name history:nil];

我知道,有几个冗余的消息保存。单个消息保存3-4次。我可能做错了什么。有些人帮忙!这是我在房间中记录消息的代码

- (NSFetchedResultsController *)fetchedResultsController{
if (fetchedResultsController == nil)
{
    NSManagedObjectContext *moc = [[self appDelegate] managedObjectContext_message];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject"
                                              inManagedObjectContext:moc];
    NSPredicate *predicate=[NSPredicate predicateWithFormat:@"bareJidStr=%@",_thisRoom.roomJID.bare];
    NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sd1, nil];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:entity];
    [fetchRequest setSortDescriptors:sortDescriptors];
    [fetchRequest setPredicate:predicate];
    [fetchRequest setFetchBatchSize:20];
    fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                   managedObjectContext:moc
                                                                     sectionNameKeyPath:nil
                                                                              cacheName:nil];
    [fetchedResultsController setDelegate:self];

    NSError *error = nil;
    if (![fetchedResultsController performFetch:&error])
    {
        DDLogError(@"Error performing fetch: %@", error);
    }   
}
return fetchedResultsController;}

3 个答案:

答案 0 :(得分:1)

我想我找到了邮件重复问题的答案。 主要问题是我在房间里发送的信息在每个房间加入时重复。 我做的是当我发送消息时,我将一个deviceID作为xmppmessage的子元素。收到消息后,我检查子元素。如果devce id匹配,它与我之前发送的相同消息及其已经存在于核心数据中,因此丢弃该消息。

- (void)sendMessageWithBody:(NSString *)messageBody
{
if ([messageBody length] == 0) return;

NSXMLElement *body = [NSXMLElement elementWithName:@"body" stringValue:messageBody];
XMPPMessage *message = [XMPPMessage message];
[message addChild:body];


//device id is used, so that the my message element will be unique 
NSString *uuidString=[UIDevice currentDevice].identifierForVendor.UUIDString;
NSXMLElement *myMsgLogic=[NSXMLElement elementWithName:@"myMsgLogic" stringValue:uuidString];
[message addChild:myMsgLogic];

[self sendMessage:message];
}

然后在xmppstream中收到消息。处理它 在XMPPRoomCoreDataStorage中,有一个名为

的方法
 - (void)handleIncomingMessage:(XMPPMessage *)message room:(XMPPRoom *)room

在此做消息排序逻辑。没有粘贴整个代码:

- (void)handleIncomingMessage:(XMPPMessage *)message room:(XMPPRoom *)room
{
  XMPPLogTrace();

XMPPJID *myRoomJID = room.myRoomJID;
XMPPJID *messageJID = [message from];


NSString *uuidString=[UIDevice currentDevice].identifierForVendor.UUIDString;

NSString *messageLogic= [[message elementsForName:@"myMsgLogic"].firstObject stringValue];

if ([uuidString isEqualToString:messageLogic]) {
    return;
}

 //rest code is already there in the method
 }

答案 1 :(得分:1)

在搜索并尝试了很多后,我得到了收集群组重复消息的结论。 XMPP效果最好,但实际问题是:

[room activate:[self appDelegate].xmppStream];

当我们活跃那个房间时,它实际上会增加一个听众。所以只激活一次

答案 2 :(得分:0)

另一种方法是创建NSPredicate

检索您的回复消息(这意味着您已在会议室内发送了一条消息,并且XMPP服务器已收到该消息并重新发送给该房间的所有(广播)占用者,其中包含 nameRoom @ muc.server.com

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (messageStr CONTAINS[cd] %@)", [NSString stringWithFormat:@"from=\"%@\"",[xmpp sharedInstance].xmppStream.myJID.bare]];

如果您要显示您发送的消息( yourClientId@server.com ),请将字符串更改为更改为

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (messageStr CONTAINS[cd] %@)", [NSString stringWithFormat:@"to=\"%@\"",[xmpp sharedInstance].xmppStream.myJID.bare]];

所以,不需要修改框架。