1

我已经使用 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;}
4

3 回答 3

1

我想我找到了消息重复问题的答案。主要问题是我在房间里发送的信息在每个房间加入时都重复了。我所做的是,当我发送消息时,我将 deviceID 作为 xmppmessage 的子元素。收到消息后,我检查子元素。如果设备 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
 }
于 2014-11-05T12:26:42.207 回答
1

在搜索和尝试了很多之后,我有一个结论来接收组的重复消息。XMPP 效果最好,但实际问题是:

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

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

于 2015-12-03T12:38:32.803 回答
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),请将字符串by更改

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

因此,无需修改框架。

于 2015-01-19T14:28:13.233 回答