将三个实体分组为多对多关系

时间:2013-05-11 08:15:36

标签: iphone objective-c core-data

在过去的几天里,我一直在努力弄清楚如何实现这一目标,而我的知识却无法实现。

我设计了三个实体List<< - >>商品<< - >>存储在核心数据模型设计器中。它们中的每一个都只有一个名为“name”的属性。

目标是选择一个列表,然后显示按商店分组的列表中的所有项目。

我试过用:

    // Set entity.
    entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set object filters.
    predicate = [NSPredicate predicateWithFormat:@"ANY list.name == %@", self.list.name];
    [fetchRequest setPredicate:predicate];

    // Set FRC
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"store.name" cacheName:nil];

错误:

'Invalid to many relationship in setPropertiesToFetch: (store.name)'

这样也可以手动填充行(我还不知道怎么做):

    // Set entity.
    entity = [NSEntityDescription entityForName:@"Store" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set object filters.
    predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(item.list, $x, $x.name == %@).@count > 0", self.list.name];
    [fetchRequest setPredicate:predicate];

    // Set FRC
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"name" cacheName:nil];

错误:

'Only allowed one toMany/manyToMany relationship in subquery expression collection (SUBQUERY(item.list, $x, $x.name == "List02"))'

还尝试了Fetched Properties和其他无法到达的方式。

有什么想法吗?

的问候。 佩德罗。

2 个答案:

答案 0 :(得分:1)

好的,这是解决方案(danypata& Martin R给我钥匙)。

要实现这一点,您应该添加一个新实体,以打破多对多关系。最终的核心数据模型是:List<< - >>商品< - >> ItemStore<< - >商店。 “ItemStore”实体不需要任何属性,只需要关系。

代码......

- (NSFetchedResultsController *)fetchedResultsController
{
    [...]

    // Set entity.
    entity = [NSEntityDescription entityForName:@"ItemStore" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];


    // Set object filters.
    predicate = [NSPredicate predicateWithFormat:@"ANY item.list.name == %@", self.list.name];
    [fetchRequest setPredicate:predicate];

    // Edit the sort key as appropriate.
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"item.name" ascending:YES];
    sortDescriptors = @[sortDescriptor];
    [fetchRequest setSortDescriptors:sortDescriptors];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Set FRC.
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"store.name" cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [...]
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    Item *item;
    ItemStore *itemStore;

    [...]

    itemStore = (ItemStore *)[self.fetchedResultsController objectAtIndexPath:indexPath];
    item = itemStore.item;
    cell.textLabel.text = item.name;

    [...]

 }

最后的说明:

  • 打破与新实体(ItemStore)和两个一对多关系(Item< - >> ItemStore& ItemStore<<> Store)的多对多关系。
  • 由于Item的“store”关系是可选的(在我的模型中),因此不检索没有Store的项目,如果你想这样做,你应该默认将它们分配给“No Store”对象。

谢谢大家。 佩德罗。

答案 1 :(得分:0)

正如已经指出的,如果一个项目可以在多个商店中,则无法按商店获取商品和分组。但是,在表视图中使用NSFetchedResultsController或类似的东西,这仍然是可能的(并且很常见)。

只需获取您要分组的实体,在本例中为Store。相应地调整表格视图datasource方法:

部分数量:

return _fetchedResultsController.fetchedObjects.count

标题:

Store *store = _fetchedResultsController.fetchedObjects[indexPath.section];
return store.name;    

部分中的行数:

Store *store = _fetchedResultsController.fetchedObjects[indexPath.section];
return store.items.count;

商店中的一件商品:

Store *store = _fetchedResultsController.fetchedObjects[indexPath.section];
Item *item = [[store.items sortedArrayUsingSortDescriptors:@[
     [NSSortDescriptor sortDescriptorWithKey:@"sortAttribute" ascending:YES]]
     objectAtIndex:indexPath.row];
// configure cell with information from item.

所以虽然这是可能的,但也许您仍然想重新考虑您的数据模型。一件商品在多个商店中真的有意义吗?如果不是,您可以使用普通的vanilla fetched results controller。