如何在 Realm 中通过 NSDate 属性正确查询对象?

Posted

技术标签:

【中文标题】如何在 Realm 中通过 NSDate 属性正确查询对象?【英文标题】:How to query object by NSDate property correctly in Realm? 【发布时间】:2019-06-12 10:39:48 【问题描述】:

我有以下场景,我在 Realm 上存储一个具有当前日期的对象,如下所示:

RLMChatMessage *chat = [[RLMChatMessage alloc] init];
chat.chatFrom = from;
chat.chatTo = to;
chat.timeStamp = [NSDate date];

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock: ^
      [realm addObject: chat];
];

为了将时间戳发送到服务器,我将其转换为 NSString,如下所示:

NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:  @"YYYYMMddHHmmssSSS”]; // Capital ’S’ is milliseconds
[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
return [dateFormat stringFromDate: date];

NSString中时间戳的结果是:20190612090741181,格式为“YYYYMMddHHmmssSSS”。

当我收到特定时间戳的确认消息时,我将 NSString 转换回 NSDate:

NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat: @"YYYYMMddHHmmssSSS”];
[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
return [dateFormat dateFromString: strTime];

然后查询带有时间戳的聊天(使用上述代码创建的 NSDate 对象)如下:

RLMResults *results = [RLMChatMessage objectsWhere:@"timeStamp == %@", date];
return results.firstObject;

很遗憾,结果没有找到任何对象。不知何故,Realm 似乎无法找到带有 NSDate 时间戳的聊天对象。 使用 Realm Browser 应用程序查看数据库,我可以看到具有以下 NSDate 的 NSDate 属性:

Xcode 中用于将 NSString 时间戳转换为 NSDate 的 NSLog 输出如下所示:

所以两者都显示相同的 NSDate 时间戳。我假设两者都将 NSDate 对象打印到我机器的本地时间。那么,Realm 怎么找不到聊天对象呢?我有点迷失在这里。希望有人能帮帮我。

【问题讨论】:

为了将时间戳发送到服务器,我将其转换为 NSString,如下所示: 为什么?此外,如果您要转换为存储在服务器上的字符串,它看起来像是屏幕截图中的 Date 对象,而不是字符串。你能澄清一下吗? 转换后的字符串为:20190612090741181,发送到服务器,为UTC时间,格式如下:YYYYMMddHHmmssSSS。无论如何,在最后一个屏幕截图中,您可以看到将 20190612090741181 (UTC) 时间转换为 NSDate 对象是正确的。 NSLog 输出与存储在 Realm 数据库中的输出相同。但仍无法通过 timeStamp 从 Realm 数据库中以编程方式获取该模型对象。 对不起,我不清楚。日期就是日期。没有理由跳过将其转换为字符串以进行保存和返回的麻烦。只需将其作为 Date 对象存储在 Realm 中即可。哦,Realm 以以下格式存储日期对象2019-06-13T14:25:04.433Z 不确定这是什么意思要将时间戳发送到服务器,我将其转换为 NSString 就好像它已转换为 NSString,然后它与您的 Realm 对象不匹配,这是一个 NSDate chat.timeStamp = [NSDate date]; 那么它是如何工作的。我知道你回答了你自己的问题,但似乎有很多不必要的工作正在进行。只需将日期用作日期,而不是将其转换为字符串并返回。 服务器需要一个通过网络发送的时间。如何通过网络发送 NSDate 对象?无论是作为整数还是作为指示时间的字符串,在这两种方式中,NSDate 对象都需要转换为整数或字符串。我使用 NSString 类最终将内容转换为字符数组以通过网络发送。 【参考方案1】:

我找到了解决方案,似乎将格式为“YYYYMMddHHmmssSSS”的 NSString 时间转换为 NSDate 会丢失一些信息或准确性。 结果,存储在数据库中的原始 NSDate 对象与从 NSString 转换而来的对象不匹配。因此,我没有像这样为当前时间分配 timeStamp:[NSDate date],而是重新创建了一个新的 NSDate 对象,其格式为“YYYYMMddHHmmssSSS”,如下所示:

- (NSDate*) timeStampNowWithFormat: (NSString*) format 
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat: format];
    [dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
    NSString *stringDate = [dateFormat stringFromDate: [NSDate date]];

    return [dateFormat dateFromString: stringDate];


// ...
// ...

RLMChatMessage *chat = [[RLMChatMessage alloc] init];
chat.chatFrom = from;
chat.chatTo = to;
chat.timeStamp = [self timeStampNowWithFormat: @"YYYYMMddHHmmssSSS"];

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock: ^
      [realm addObject: chat];
];

底线,一旦您将 NSDate 对象转换为 NSString,然后从该 NSString 重新创建一个新的 NSDate,如果时间精度小于毫秒(即微秒),则两个 NSDate 对象不再相等。 我花了一天多的时间才弄明白。

【讨论】:

以上是关于如何在 Realm 中通过 NSDate 属性正确查询对象?的主要内容,如果未能解决你的问题,请参考以下文章

Realm create() 无法将 JSON 字符串解析为 NSDate?

从 NSDate 到 NSString 的转换,属性上的核心数据迁移未正确显示字符串

如何在我的浓缩咖啡测试中通过 id 查看?

如何在 Solidity 中通过多个属性查询结构?

如何在 TypeScript 中通过索引访问通用对象的属性?

如何在 Mule 4 中通过 ActiveMQ 传递属性