核心数据:获取特定对象的多对多关系中的所有实体?

Posted

技术标签:

【中文标题】核心数据:获取特定对象的多对多关系中的所有实体?【英文标题】:Core Data: Fetch all entities in a to-many-relationship of a particular object? 【发布时间】:2010-12-30 11:48:25 【问题描述】:

在我的 iPhone 应用程序中,我正在使用具有两个实体(ItemProperty)的简单核心数据模型:

物品 名称属性

房产 名称 价值项目

Item 有一个属性(名称)和一个一对多关系(properties)。它的反比关系是item属性有两个属性对应的反比关系。

现在我想在两个级别的表格视图中显示我的数据。第一个列出所有项目;选择一行时,将推出一个新的UITableViewController在我的UinavigationController的堆栈上。新的 UITableView 应该显示所选项目的所有属性(即它们的名称)。

为了实现这一点,我使用了一个存储在实例变量中的NSFetchedResultsController。在第一层,像这样设置 NSFetchedResultsController 时一切正常:

-(NSFetchedResultsController *) fetchedResultsController 
    if (fetchedResultsController) return fetchedResultsController;

    // goal: tell the FRC to fetch all item objects.
    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.moContext];
    [fetch setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    [fetch setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetch setFetchBatchSize:10];

    NSFetchedResultsController *frController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.moContext sectionNameKeyPath:nil cacheName:@"cache"];
    self.fetchedResultsController = frController;
    fetchedResultsController.delegate = self;

    [sort release];
    [frController release];
    [fetch release];

    return fetchedResultsController;

但是,在二级UITableView上,我好像做错了什么。我以类似的方式实现了 fetchedresultsController:

-(NSFetchedResultsController *) fetchedResultsController 
    if (fetchedResultsController) return fetchedResultsController;

    // goal: tell the FRC to fetch all property objects that belong to the previously selected item
    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];

    // fetch all Property entities.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Property" inManagedObjectContext:self.moContext];
    [fetch setEntity:entity];

    // limit to those entities that belong to the particular item
    NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"item.name like '%@'",self.item.name]];
    [fetch setPredicate:predicate];

    // sort it. Boring.
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    [fetch setSortDescriptors:[NSArray arrayWithObject:sort]];

    NSError *error = nil;
    NSLog(@"%d entities found.",[self.moContext countForFetchRequest:fetch error:&error]);
    // logs "3 entities found."; I added those properties before. See below for my saving "problem".
    if (error) NSLog("%@",error);
    // no error, thus nothing logged.

    [fetch setFetchBatchSize:20];

    NSFetchedResultsController *frController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.moContext sectionNameKeyPath:nil cacheName:@"cache"];
    self.fetchedResultsController = frController;
    fetchedResultsController.delegate = self;

    [sort release];
    [frController release];
    [fetch release];

    return fetchedResultsController;

现在变得越来越奇怪了。上面的NSLog 语句返回了所选项目的正确属性数。但是,UITableViewDelegate 方法告诉我没有属性:

-(NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section 
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    NSLog(@"Found %d properties for item \"%@\". Should have found %d.",[sectionInfo numberOfObjects], self.item.name, [self.item.properties count]);
    // logs "Found 0 properties for item "item". Should have found 3."
    return [sectionInfo numberOfObjects];

相同的实现在第一层也能正常工作。

它变得更奇怪了。我实现了某种 UI 来添加属性。我通过Property *p = [NSEntityDescription insertNewObjectForEntityForName:@"Property" inManagedObjectContext:self.moContext]; 创建一个新的Property 实例,设置关系并调用[self.moContext save:&amp;error]。这似乎可行,因为 error 仍然是 nil 并且对象被保存(我可以在记录 Item 实例时看到属性的数量,见上文)。但是,不会触发委托方法。这在我看来是因为 fetchRequest(Controller) 可能搞砸了。

有什么想法吗?我搞砸了第二个获取请求吗?这是获取特定实例的多对多关系中所有实体的正确方法吗?

【问题讨论】:

【参考方案1】:

您需要实际执行表视图控制器的获取:

// ...create the fetch results controller...    
NSError *fetchRequestError;
BOOL success = [fetchedResultsController performFetch:&fetchRequestError];

【讨论】:

方式...太...简单。非常感谢,我该去喝杯咖啡了。 :) 嗯,它是卡在一大堆其他代码中间的一小段代码。 Core Data 是一头复杂的野兽。 不好意思我有点糊涂了,上面的代码sn-p替换了哪一行? 这几行代码应该放在[sort release]之前,接近末尾。

以上是关于核心数据:获取特定对象的多对多关系中的所有实体?的主要内容,如果未能解决你的问题,请参考以下文章

NSFetchedResultsController:如何从实体的多对多关系中获取sectionName

核心数据:与状态的多对多关系

针对特定集合的多对多关系核心数据查询

Remove() 不适用于实体框架中的多对多关系

NSPredicate 在核心数据中的多对多关系

JPA 与存储在不同数据库中的用户实体的多对多关系