【发布时间】:2026-01-07 23:00:02
【问题描述】:
我正在尝试使用 XMPP 构建聊天应用。它工作正常。但是,我发现当我收到其他人的离线消息时,我的聊天列表变得混乱。那是因为离线消息的时间戳是按服务器时间存储的,而服务器时间与我设备的时间不同。所以你能告诉我如何调整我从服务器或其他解决方案获得的时间来解决这个问题,非常感谢!!
【问题讨论】:
我正在尝试使用 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];
这里,这些代码是处理存储到核心数据的消息时间戳。我们使用“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)
【讨论】:
func xmppAutoTime(sender: XMPPAutoTime!, didUpdateTimeDifference timeDifference: NSTimeInterval) 的XMPPAutoTimeDelegate 来检查它
我也遇到过 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];
【讨论】: