Я не совсем уверен, что ваш вопрос задает.Так, например, вы хотите перебрать все категории и все вещи в этой категории, вы сначала сделаете запрос для сущностей категории без предиката (это вернет все объекты категории) и перебираете все те с быстрым перечислением:
//iOS 5 way of doing it
NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntity:@"Category"];
NSArray* arrayOfObjects = [context executeFetchRequest: request withError: nil];
for (Category* cat in arrayOfObjects)
{
//iterate over all the things in that category
for (Thing* thing in cat.things){
{
//do something?
}
}
Для вашего первого примера заполнения табличного представления вещами в категории:
Если у вас есть категория, вы получите вещи очень легко, как это:
NSSet* things= category.things;
//you can get it into an array by sorting it somehow or just get it like that.
NSMutableArray* things = [[category.things allObjects] mutableCopy];
Вы можете повторить это обычным способом или использовать их в качестве источника данных для просмотра таблицы.Если у вас нет категории, вам нужно что-то отличить, и в этом случае вы бы настроили предикат следующим образом:
NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntity:@"Thing"];
NSPredicate* pred = [NSPredicate predicateWithFormat:@"(relationToCat.DestAtt = %@)",howToDestinguish];
Это вернет все Вещи, которые связаны с категорией, которая имеетатрибут.
Для вашего второго примера, вы должны установить NSPredicate, чтобы получить все ThingLocations для этого конкретного Thing.Затем переберите их и сложите значения в местах.Если вы хотите сделать это для каждой категории во всем, то вам просто потребуется вложить цикл for, начинающийся с категорий.затем для каждой вещи получите все ThingLocations и для каждого из них сложите значения.
Я надеюсь, что это отвечает на ваши вопросы.Отношения ко-многим являются просто множествами и могут рассматриваться как таковые.Я считаю, что мышление снизу вверх помогает мне сформировать предикаты.думая, что мне нужны все вещи в этой категории, поэтому я бы настроил сущность вещей и соединил ее с категорией в предикате.
Редактировать: пример NSFetchedResultsController В вашем .hПосле объявления вашего суперкласса добавьте NSFetchedResultsControllerDelegate
к реализованным делегатам.
Создайте ivar: @property (nonatomic, retain) NSFetchedResultsController * fetchedResultsController;
На стороне реализации, которую я виделдва разных подхода, первый - написание пользовательского метода доступа для свойства, которое его там инициализирует, другой - просто сделать это в viewDidLoad
, в любом случае настройка выглядит следующим образом:
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Thing" inManagedObjectContext:context];
NSPredicate* pred=[NSPredicate predicateWithFormat:@"(relToCat.something=%@)",something];
[fetchRequest setPredicate:pred];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20]; //tells it how many objects you want returned at a time.
//this is for displaying the things in some sort of order. If you have a name attribute you'd do something like this
NSSortDescriptor *descriptor = [[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES] autorelease];
NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects: descriptor, nil] autorelease];
[fetchRequest setSortDescriptors:sortDescriptors];
//this is the set up. If you put a sectionNameKeyPath it will split the results into sections with distinct values for that attribute
NSFetchedResultsController *frc = nil;
frc = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context] sectionNameKeyPath:@"attribute that splits it into sections" cacheName:nil];
[frc setDelegate:self];
[self setFetchedResultsController:frc];
[frc release];
frc = nil;
//Tells it to start.
[fetchedResultsController performFetch:nil];
Затемдля методов делегата табличного представления это очень просто:
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return [[[fetchedResultsController sections] objectAtIndex:section] name];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {
return [[fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[fetchedResultsController sections] objectAtIndex: section] numberOfObjects];
}
/* If you want the bar on the right with the names of the sections...
-(NSArray*) sectionIndexTitlesForTableView:(UITableView *)tableView{
return [fetchedResultsController sectionIndexTitles];
}*/
-(UITableViewCell* )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* ident=@"cellident";
UITableViewCell *cell = [self.itemTable dequeueReusableCellWithIdentifier:ident];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:ident] autorelease];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void) configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath {
NSManagedObject* item=[fetchedResultsController objectAtIndexPath:indexPath];
//set up your cell somehow
return cell;
}
Вам также необходимо добавить методы делегата для контроллера полученных результатов.Все они очень просты и выглядят примерно так:
- (void)controllerWillChangeContent:(NSFetchedResultsController*)controller {
[tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController*) controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
NSIndexSet *set = [NSIndexSet indexSetWithIndex:sectionIndex];
switch(type) {
case NSFetchedResultsChangeInsert: [tableView insertSections:set withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteSections:set withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController*)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath*)newIndexPath
{
UITableView *tv = tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tv cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController*)controller {
[tableView endUpdates];
}
Это обновит таблицу, если в какой-то другой части программы будет добавлена вещь, она автоматически появится в таблице, если предикат совпадет.