iphone - xmpp离线消息时间戳导致聊天列表混乱

iphone - xmpp offline message timestamp lead the chat list disorder

我正在尝试使用 XMPP 构建聊天应用程序。它工作正常。但是,我发现当我收到其他人的离线消息时,我的聊天列表变得混乱了。那是因为离线消息的时间戳是按服务器时间存储的,而服务器时间与我设备的时间不同。那你能告诉我如何调整我从服务器或其他解决方案获得的时间来解决这个问题,非常感谢!!

我在保持用户项目同步方面遇到了类似的问题。我所做的是保持服务器和客户端之间的时间差。

在能够向服务器发送数据之前,客户端向服务器请求时间戳。然后它保持时间偏移。这是我的代码(responseObject 是一个字典,其中包含从服务器获取的数据)。

     NSTimeInterval serverTimestamp = [[responseObject valueForKey:@"timestamp"] unsignedIntegerValue];
     NSTimeInterval appTimestamp = [[NSDate date] timeIntervalSince1970];
     [self setServerTimeOffset:(serverTimestamp - appTimestamp)];

然后,当我发出请求时,我计算服务器时间戳:

- (NSDate *)serverDate {
    return [[NSDate date] dateByAddingTimeInterval:_serverTimeOffset];
}

如果你有和我一样的问题,我在这里找到了答案并与你分享我的解决方案。在 XMPP 中,我们有两个扩展:XEP-0202 XMPPAutoTime 和 XEP-0136 XMPPMessageArchiving。

当我们在 appDelegate 中使用 XMPPMessageArchiving 时,消息(无论在线还是离线)都会存储到核心数据中。如果消息是离线消息,时间戳将是服务器的时间。并且某些设备的时钟可能与服务器的时钟不同。我们可以使用 XMPPAutoTime 来处理设备时钟和服务器时钟之间的延迟。

在XMPPMessageArchivingCoreDataStorage.m中可以找到一个叫做

的函数
 - (void)archiveMessage:(XMPPMessage *)message outgoing:(BOOL)isOutgoing xmppStream:(XMPPStream *)xmppStream

并在此函数中找到以下代码:

        if (timestamp)
            archivedMessage.timestamp = timestamp;
        else
            archivedMessage.timestamp = [[NSDate alloc] init];

这里,这些代码是处理存储到核心的消息时间戳data.We使用"XMPPAutoTime"

调整离线消息时间戳
        if (timestamp){
            NSTimeInterval timeDiffer = [[self appDelegate].xmppAutoTime timeDifference];
            timestamp = [NSDate dateWithTimeInterval: - timeDiffer sinceDate:timestamp];
            archivedMessage.timestamp = timestamp;

        }
        else
            archivedMessage.timestamp = [[NSDate alloc] init];

这对我有用。 (当然你要导入AppDelegate,在AppDelegate中设置xmppAutoTime)

我也遇到了 XMPP 的离线时区问题。我的问题是当我第一次尝试从数据库(CoreData)中检索时获得 10 分钟的快速时间,如果我在 offline.That 中收到另一个用户的消息,问题已通过以下代码解决 在 XMPPMessageArchivingCoreDataStorage.m 你可以找到

- (void)archiveMessage:(XMPPMessage *)message outgoing:(BOOL)isOutgoing xmppStream:(XMPPStream *)xmppStream

并在这个函数中找到如下代码

   if (timestamp)
        archivedMessage.timestamp = timestamp;
    else
        archivedMessage.timestamp = [[NSDate alloc] init];

用下面的代码替换上面的代码

     if (timestamp)
        {
            NSDate *deviceTime = [[NSDate alloc] init];
            NSTimeInterval timeInterval=[deviceTime timeIntervalSinceDate:timestamp];
            timestamp=[NSDate dateWithTimeInterval:timeInterval sinceDate:timestamp];
            archivedMessage.timestamp = timestamp;
        }
        else
            archivedMessage.timestamp = [[NSDate alloc] init];