【问题标题】:iphone - xmpp offline message timestamp lead the chat list disorderiphone - xmpp 离线消息时间戳导致聊天列表乱序
【发布时间】:2026-01-07 23:00:02
【问题描述】:

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

【问题讨论】:

    标签: ios time timezone xmpp


    【解决方案1】:

    我有一个类似的问题来保持用户的项目同步。我所做的是保持服务器和客户端之间的时间差。

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

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

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

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

    【讨论】:

    • 感谢您的回答。我发现在 XMPP 中有一些扩展可以使用。方法和你的类似,效果很好。
    【解决方案2】:

    如果你和我有同样的问题,我在这里找到了答案并与你分享我的解决方案。在 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];
    

    这里,这些代码是处理存储到核心数据的消息时间戳。我们使用“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)

    【讨论】:

    • @LucaDavanzo 你需要等待几秒钟 XMPPAuatoTime 才能获得 timeDifference。您可以通过执行func xmppAutoTime(sender: XMPPAutoTime!, didUpdateTimeDifference timeDifference: NSTimeInterval)XMPPAutoTimeDelegate 来检查它
    【解决方案3】:

    我也遇到过 XMPP 的离线时区问题。我的问题是当我尝试从数据库(CoreData)中检索时,如果我处于脱机状态,当我收到另一个用户的消息时,第一次获得 10 分钟的快速时间。该问题由以下代码解决 在 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];
    

    【讨论】: