简体   繁体   中英

How to query object by NSDate property correctly in Realm?

I have the following scenario, I store an object on Realm with current date, like this:

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

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

To send the timestamp to the server, I convert it to NSString as follows:

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

The result of the timestamp in NSString is: 20190612090741181 with format of "YYYYMMddHHmmssSSS”.

When I receive an acknowledge message for the specific timestamp, I convert the NSString back to NSDate:

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

I than query the chat with timestamp (NSDate object created with the above code) as follows:

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

Sadly enough, the results has NO objects found. Somehow, Realm can't seem to find the chat object with provided NSDate timestamp. Using Realm Browser app to look in the database, I can see the NSDate property with the following NSDate: 在此输入图像描述

The NSLog output in Xcode for converting NSString timestamp to NSDate looks like this: 在此输入图像描述

So both show the NSDate timestamp the same. I assume both print the NSDate object to local time of my machine. So, how come Realm can't find the chat object? I'm kind of lost in here. Hope someone can help me out.

I found the solution, it seems that converting NSString time with format “YYYYMMddHHmmssSSS” to NSDate loses some info or accuracy. As a consequence, the original NSDate object stored in the database doesn't match with the one converted from NSString. So instead of assigning timeStamp with current time like this: [NSDate date], I recreate a new NSDate object with format “YYYYMMddHHmmssSSS” like this:

- (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];
}];

Bottomline, once you convert NSDate object to NSString and then recreate a new NSDate from that NSString, both NSDate objects aren't equal anymore if time accuracy is smaller than milliseconds (ie microseconds). It took me more than a day to figure that out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM