One to Many relationships iPhone - NSPredicate cor

2019-02-15 23:46发布

I have a have a number of calendars, which each have a number of events. I would like to find all the events for a calendar where date > x.

My method signature looks like this

-(NSArray*)eventsForCalender:(Calendar*)calender StartDate:(NSDate*)start endDate:(NSDate*)endDate;

I added an Event to a calender like this, but I don't have a clue how to go about to construct an NSPredicate for the query. Any help appreciated

-(Event*)newEventforCalender:(Calendar*)calender
{
    Event * newEvent = (Event*)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:app.managedObjectContext];

    NSMutableSet * eventsArray = [calender mutableSetValueForKey:@"Events"];
    [eventsArray addObject:newEvent];
    [app.managedObjectContext processPendingChanges];

    return newEvent;
}

alt text http://img4.imageshack.us/img4/5218/screenshot20091120at140.png

I changed the relationship name to "events" and tried the following

....
    NSEntityDescription * entity = [NSEntityDescription entityForName:@"Calendar" inManagedObjectContext:app.managedObjectContext];
    [request setEntity:entity]; 

    NSPredicate * predictate = nil;
    predictate = [NSPredicate predicateWithFormat:@"(name == %@) AND (Event.start > '%@') AND (Event.finish < '%@')", calender.name, start, endDate, nil];
    [request setPredicate:predictate];
...

However i'm getting an exception

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key Event.'

1条回答
可以哭但决不认输i
2楼-- · 2019-02-16 00:22

Some thoughts:

  1. In your model, is newRelationship really called calendar?
  2. You want to rename Events to events to follow naming conventions (entities like Event and Calendar are capitalized, while attributes like discipline and relationships like events are lowercase)
  3. Wire up the calendar and events relationships in both directions

That said and done, you could use a predicate like:

- (NSArray *) eventsForCalendar:(Calendar *)calendar startDate:(NSDate *)startDate endDate:(NSDate *)endDate {

    NSPredicate *_predicate;
    NSString *_predicateStr;
    NSSet *_calendarQueryResults;

    _predicateStr = [NSString stringWithFormat:@"(name like '%@') AND (event.start > '%@') AND (event.finish < '%@')", calendar.name, startDate, endDate];
    _predicate = [NSPredicate predicateWithFormat:_predicateStr];
    _calendarQueryResults = [_managedObjectContext fetchObjectsForEntityName:@"Calendar" withPredicate:_predicate];

    return [_calendarQueryResults allObjects];
}

This will work if the calendar name is sufficient for uniquely identifying an individual calendar. If you have two calendars with the same name, you would have to add an additional search criterium, like @"(category like '%@') ... ", calendar.category, ...

You can also use the object ID:

_predicateStr = [NSString stringWithFormat:@"(SELF == %@) AND (event.start > '%@') AND (event.finish < '%@')", calendar, startDate, endDate];

A good reference for NSPredicate programming is Apple's aptly named NSPredicate Programming Guide.

查看更多
登录 后发表回答