Reputation: 993
Hello I am trying to filter for only objects that fall under a certain time. For example, I only want objects that are before 8 AM or after 1PM.
If in my object there is a createdDate attribute and I only want to fetch objects that were created before 8AM, what would be the approach to do that?
I wanted to do it by using either of these approaches but have been getting 0 results trying out both approaches.
1.Created a separate derived attribute that returns the time portion and do a filter on that.
i.e. (Persistent)createdDate -> (Derived)createdTimeByHour
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"createdTimeByHour < 10"];
2.Setup predicate to filter based on converted createdDate.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"createdDate.hour < 10"];
Attempts:
I've tried to implement the first solution, but NSFetchRequest doesn't return to me any results. I create the derived attribute like so...
- (NSNumber *)createdTimeByHour
{
NSNumber *result;
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:[self createdDate]];
result = @([components hour]);
return result;
}
BACKGROUND PROBLEM I found I was getting 0 results because I added derived data after there was already existing objects in Core Data. These objects don't have a value in core data, but when trying to log for it after fetching all results, it creates the derived result, but never saves or stores data in core data. I was hoping I wouldn't need to store this in Core Data, but in the end, it makes sense to do this since I will be querying by this field often.
SIMPLE SOLUTION So in a very simple case, in older to filter by time, you must create an attribute that stores this value in core data. You cannot filter by time straight from NSDate to my knowledge.
ADVANCED SOLUTION If you are adding this field when there already exists objects in core data, you must process each object in core data to store this result.
Upvotes: 2
Views: 92
Reputation: 80265
I think the easiest way for Core Data is to use solution 1, a derived property to return the hour of the day. You could also persist it (which you would need to do to use it in a NSFetchedResultsController
); you can do this automatically whenever the createdDate
is set (e.g. in awakeFromInsert
).
E.g.
-(void) awakeFromInsert {
[super awakeFromInsert];
self.createdDate = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps =
[calendar components:NSCalendarUnitHour fromDate: [NSDate date]];
self.hour = @(comps.hour);
}
Upvotes: 1