使用关系的NSFetchedResultsController和表

时间:2014-04-13 16:06:26

标签: ios uitableview core-data nsfetchedresultscontroller

作为一个简单的例子,假设我有2个具有多对多关系的实体。第一个实体被称为" Projects"和第二个"员工"。项目实体可以有一个或多个员工,员工可以在一个或多个项目上。

为简单起见,Project有一个名为projectName的属性,以及与Employee一起调用withEmployees的多对多关系。相反,Employee具有employeeName和与myProjects项目的多对多关系。

使用NSFetchedResultsController我想要一个将projectName作为行名称和employeeName的表。使用Project作为获取的实体,我可以轻松获取每个项目并创建相应的部分名称。但是,在计算numberOfRowsInSection时会出现问题。当获取的结果撤回项目的一条记录时,numberofrows只看到一个实体,因为它没有查看.withEmployees关系中找到的NSSet。这意味着只输出一个员工而不是NSSet关系中的数字计数。

如何在表格中使用多对多关系来最好地克服这个问题?

感谢。

以下是fetchedcontroller的代码:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Projects" 
     inManagedObjectContext:self.managedObjectContext];

[fetchRequest setEntity:entity];

NSSortDescriptor *firstSort = [[NSSortDescriptor alloc] initWithKey:@"projectName"
                                                                      ascending:NO];

NSArray *sortDescriptors = @[firstSort];

[fetchRequest setSortDescriptors:sortDescriptors];


_fetchedController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:self.managedObjectContext
                                                                      sectionNameKeyPath:@"projectName"  
                                                                                 cacheName:nil];

3 个答案:

答案 0 :(得分:1)

我终于找到了答案。我所拥有的实体关系如上所述都很好。问题再次是获得通过to to many关系返回的正确行数。我用以下方式解决了这个问题:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    Projects *project = [self.fetchedController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];

return [project.withEmployees count];

}

通过上面我使用了相应的部分,因为我知道总有一行包含一组未知大小,我创建了一个索引路径,它查找每个部分的唯一一个头记录(项目) 。然后我只是查看构成关系的NSSet并简单地返回它的计数。现在我们得到每个部分正确的行数。

至于细胞本身:

Projects *project = [self.fetchedController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:atIndex.section]];

UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:atIndex];

NSArray *empArray = [project.withEmployees allObjects];

Employee *employee = [empArray objectAtIndex:atIndex.row];

cell.textLabel.text = employee.firstName;

}

这里的关键是获取一节记录,然后提取构成多对多关系的所有数据。我再次需要创建一个索引路径,以便只获取父记录。现在使用行我可以遍历数组来获取每个元素。

答案 1 :(得分:0)

这样的东西
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id<NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
    return [sectionInfo numberOfObjects];
}

这假设您已在提取的结果控制器的sectionNameKeyPath:电话中传递了正确的-initWithFetchRequest:managedObjectContext:sectionNameKeypath:cacheName:

附注:关系名称通常遵循与属性或属性相同的命名规则。使用myProjectswithEmployees代替projectsemployees。它会让您的代码更好:fred.projects代替fred.myProjectslawnmower.employees代替lawnmower.myEmployees

答案 2 :(得分:0)

我还不能发表评论,所以请将此作为答案并可能添加到上面的代码中:

我设法在NSSet中检索关系的实体并在tableview中显示它。

但是我现在正试图对该tableview实现slide-to-delete,而我的NSFRC无法注册关系数组中对象的删除。

在这个例子中,这意味着:我可以删除一个Project对象,但是如果我删除了一个Employee对象,它会崩溃,因为它会注册(0,0)添加/删除的行。

我以相同的方式获取它,然后删除该对象:

NSArray *empArray = [project.withEmployees allObjects];

Employee *employee = [empArray objectAtIndex:atIndex.row];

[context deleteObject:employee];

你有任何机会可以解决这个问题吗?

我目前在我的NSFRC中没有谓词,如果它检查了project.employee的东西会改变什么?或者我应该使用2个NSFRC,一个加载Projects并设置部分,一个加载Employees并加载行?我认为他们在检测到已删除的对象时可能仍然会干扰。

相关问题