predicate search on array with Core date Entity with NSDates for just a given calendar unit in date.

i have an array of entities with date objects in relationship end. I know how to filter out objects for given dates or date ranges using predicates. my situation is that now i need to filter out objects matching a given value of a calendar unit. like year 2001 or month 4.


now for year this seems simple cause i can just make a start date and end date with jan 1 and dec 31 for given year. but for month week this is an impossible task to calulate start and end dates of each week or even months as there are leap years. there has to be a simpler way where i can just mention in the predicate as to which date component i want to be matched.


please let me know how to do it.


thanks.

Answered by jsslai in 36711022

Use NSPredicate +predicateWithBlock and create date components from the date in the block and compare the components.

I'm quite sure you can't do that with Core Data and NSPredicate. You have to filter the entities after fetching them from Core Data.

yes i have already fetched the entities. now i want to filter them using predicate filtering for nsarray.

Accepted Answer

Use NSPredicate +predicateWithBlock and create date components from the date in the block and compare the components.

Sorry didnt get it? How does oredicate with block work?

NSCalendar *calendar = [NSCalendar currentCalendar];
   
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSDate *date, NSDictionary<NSString *,id> * bindings) {
   NSDateComponents *components = [calendar components:NSCalendarUnitYear fromDate:date];
       
   if (components.year == 2015) {
      return YES;
   } else {
      return NO;
   }
}];
   
NSArray *dates = @[[NSDate date]];
NSArray *filteredDates = [dates filteredArrayUsingPredicate:predicate];

To be honest I stay away from blocks as I don't understand them fully.


over here what should be my arguments to the block if the entity i am evaulating is A and the relation object is Date.date.


so basically i want all A who have relationship Date's attribute date having year 1998 (for example)

Something like this?


@interface Entity : NSObject
@property (nonatomic) NSDate *date;
@end

@implementation Entity

@end

Entity *entity1 = [Entity new];
entity1.date = [NSDate new];
Entity *entity2 = [Entity new];
entity2.date = [NSDate dateWithTimeIntervalSince1970:902384252]; / 
NSArray *entities = @[entity1, entity2];
NSArray *filteredEntities = [self entities:entities withYear:1998];

- (NSArray *)entities:(NSArray *)entities withYear:(int)year {
    NSCalendar *calendar = [NSCalendar currentCalendar];
   
    NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(Entity *entity, NSDictionary<NSString *,id> * bindings) {
        NSDateComponents *components = [calendar components:NSCalendarUnitYear fromDate:entity.date];
       
        if (components.year == year) {
            return YES;
        } else {
            return NO;
        }
    }];
   
    return [entities filteredArrayUsingPredicate:predicate];
}
        NSPredicate *datePredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
            EntityA *entityAObject = (EntityA*)evaluatedObject;
            int component = [[NSCalendar currentCalendar] component:calendarUnit fromDate:entityAObject.date.date];
            if (component == [calendarUnitValue intValue])
            {
                return YES;
            }
            else
            {
                return NO;
            }
        }];


did this. works perfectly fine! thanks a lot jsslai

predicate search on array with Core date Entity with NSDates for just a given calendar unit in date.
 
 
Q