如何处理MUC聊天消息 – 复制消息

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

这是我join我的房间之前,我已经保存的消息)

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;} 

我想我find了一个消息重复问题的答案。 主要问题是我在房间里发送的消息在每个房间都重复了。 我所做的是当我发送一条消息时,我保留了一个deviceID作为xmppmessage的子元素。 在接收消息时,我检查了子元素。 如果devce id匹配,那么它与我先前发送的相同的消息已经在核心Data中,因此丢弃该消息。

 - (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 

对此做消息sorting逻辑。 不粘贴整个代码:

 - (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 } 

经过search和尝试了很多,我有一个结论,为群接收重复的消息。 XMPP效果最好,但实际问题是:

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

当我们活动那个房间时,它实际上增加了一个监听器。 所以活动只有一次

另一种方法是创build一个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 ),则将string by更改

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

所以,不需要修改框架。