I have implemented one to one chat using XMPP framework It has extensive support in one to one chat. Message archiving and fetching is way simple. But i see, very difficulty in handling a group chat message saving and displaying. The sorting and predicates are failing. duplicate messages are shown.
This is how i join a room before i fetch my already saved message)
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];
I see, there are several redundant saving of messages. A single message is saved 3-4 times. What might i be doing wrong. Some body pls help! This is the code i do for fecthing messages in a room
- (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;}
I think i found out an answer for the message duplication issue. The main issue was the message i am sending in the room was repeated on each room joining. What i did was when ever i sent a message i kept a deviceID as child element for the xmppmessage. On recieving on the message, i check the child element. If the devce id matches, its the same message i send earlier and its already in the core Data, So discard the message.
- (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];
}
Then on message recieving in xmppstream. handle it In XMPPRoomCoreDataStorage, there is a method called
- (void)handleIncomingMessage:(XMPPMessage *)message room:(XMPPRoom *)room
on this do the message sorting logic. Not pasting the entire code:
- (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
}
After searching and trying a lot i have a conclusion for receving duplicate messages for group. XMPP works best but actual issue was:
[room activate:[self appDelegate].xmppStream];
When ever we active that room it actually adds a listener. So Active only once.
Another way to do that is creating a NSPredicate
:
Retrieve your echo messages (this means that you has sent a message within the room, and the XMPP server has received that message and re-sent to all (broadcast) occupants of the room with a bare like nameRoom@muc.server.com)
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (messageStr CONTAINS[cd] %@)", [NSString stringWithFormat:@"from=\"%@\"",[xmpp sharedInstance].xmppStream.myJID.bare]];
If you want to show the messages that has been sent by you ( yourClientId@server.com) then change the string from by to
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (messageStr CONTAINS[cd] %@)", [NSString stringWithFormat:@"to=\"%@\"",[xmpp sharedInstance].xmppStream.myJID.bare]];
So, no need to modify the framework.
来源:https://stackoverflow.com/questions/26681309/how-to-handle-muc-chat-messages-messages-duplicating