1
votes

I have a Core Data entity which has a date attribute. I would like to write a predicate to extract all dates within a specific month, e.g. July, irrespective of year. How can this be achieved? Thanks

2

2 Answers

6
votes

You can create a new method on your entity, which we'll call monthOfDate. This method simply uses [self dateAttribute] and NSDateComponents to extract what the month of the date is.

Then you can write a predicate that does:

//assuming 1-based month indexing
NSPredicate * julyEntities = [NSPredicate predicateWithFormat:@"monthOfDate = 7"]; 

The trick here is realizing that the left keypath of your predicate will result in a method invocation. So if you set the left keypath to "monthOfDate", it will end up invoking your monthOfDate method and using the return value of the method as the comparison value in the predicate. Neat!

0
votes

can't comment yet so asking this way.

How did you end up implementing this? I tried adding a method in the managed object class but once the predicate fires it says it can't find the keypath monthOfDate?

Updated with both files:

.h file:

@property (nonatomic,retain) NSNumber *monthOfDate;
-(NSNumber *)monthOfDate;

.m file:

@synthesize monthOfDate;

-(NSNumber *) monthOfDate
{
NSDate *date = [self start];
NSDateComponents *components = [[NSCalendar currentCalendar]components: NSCalendarUnitMonth fromDate:date];
NSNumber *month = [NSNumber numberWithInteger:[components month]];
return month;
}

Update 2

The code above is in the auto-generated Event class (NSmanaged object). I might move my custom code to a category later but so far no model revisions are necessary.

Below is the FetchedResultsController (in a uiviewcontroller class) setup with mentioned predicate:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

NSEntityDescription *entity = [NSEntityDescription
                               entityForName:@"Event" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];

NSSortDescriptor *sortfix = [[NSSortDescriptor alloc]initWithKey:@"timeStamp" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortfix,nil]];
[fetchRequest setFetchBatchSize:20];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"client == %@ AND monthOfDate = %d", clientMO,[NSNumber numberWithInteger:6]];
[fetchRequest setPredicate:predicate];


NSFetchedResultsController *theFetchedResultsController =

[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:managedObjectContext sectionNameKeyPath:sectionKeyPathProperty
                                               cacheName:nil];

//sectionKeyPathProperty is a variable that let's me choose one of multiple transient properties I have created for creating relevant sections.

self.fetchedResultsControllerClient = theFetchedResultsController;
_fetchedResultsControllerClient.delegate = self;

return _fetchedResultsControllerClient;