1

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;}
Mickaël Rémond
  • 9,035
  • 1
  • 24
  • 44
alin andrews
  • 39
  • 1
  • 7
  • why downvoted? The question is genuine and the answer to this question will help anyone doing groupchat using robbie hanson xmpp framework. There is an issue of same messages repitted 3-4 times in this framework. if someone has found any work around, that will save – alin andrews Nov 01 '14 at 10:04
  • Don't worry buddy.Be happy.Now you can see your question with no down voted.I have up voted your question.Just because I totally agree with you question Its genuine question. – Arpan Dixit Nov 06 '14 at 12:50

3 Answers3

1

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
 }
alin andrews
  • 39
  • 1
  • 7
  • Hello @alin, I want to ask one thing , How we can save group chat in core data ? I am unable to retrieve data from core data like we can retrieve for peer-peer chat. – Sushil Sharma Apr 20 '15 at 09:48
  • Sushil. XMPPRoomMessageCoreDataStorageObject. This is the object for room messages. Give right parameters for core data fetch (like room jids, stream etc) Then you will get the saved room messages. – alin andrews Apr 24 '15 at 06:56
  • Thanks for reply @Alin,But for retrieving ,we need to activate coreDataStorage in appDelegate. How we do that? How to activate coreDataStorage ? – Sushil Sharma Apr 24 '15 at 07:39
  • @alinandrews i tried your solution but still getting duplicate messages could you please tell me how to fix this.I already ask a question http://stackoverflow.com/questions/29538479/ios-chat-application-using-xmpp-protocolejabbered-room-chat-issue – alok srivastava May 03 '15 at 11:36
  • @alinandrews Xmpp execution is faster then normal iOS execution. May we can say this is patch but problem was active stream. But Hey nice logic. – Siten Dec 03 '15 at 12:46
1

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.

Matt
  • 74,352
  • 26
  • 153
  • 180
Siten
  • 4,515
  • 9
  • 39
  • 64
0

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.

Moral
  • 111
  • 9
  • Good one Moral. I had tried this. But on very fast message deliveries, the messages was repetiting. And also the msgLogic method can be done without any database operation. So, I opted for that method. – alin andrews Jan 20 '15 at 09:12
  • @alinandrews did you get the solution? I have same question – Siten Nov 26 '15 at 11:36