显示核心数据:如果属性具有相同的名称显示一次

我已经看过许多谓词问题,我已经阅读了文档,没有什么东西似乎跳出来作为我的问题的答案。

我有一个名为材料的核心数据实体,我有属性类别子类别说明

我有三个UITableViewControllers并在每个我想要使用谓词来显示,如下所示:

TableViewController 1:只有类别(不重复类别名称)

select一个类别并转到TableViewController 2。

TableViewController 2:显示子类别(不重复的子类别名称)

select一个子类别并转到TableViewController 3列出该类别和子类别中的所有项目。

如果不使用核心数据模型中的三个实体,我可以这样做吗?

我已经试过在我的fetchedResultsController方法中使用下面的谓词代码,但利用:

 Materials * materials = [[Materials alloc]init];//this doesn't feel like it belongs inside a fetchedResultsController NSPredicate * predicate = [NSPredicate predicateWithFormat:@"category == %@", materials.category]; fetchRequest.predicate = predicate; 

这是我第一次试图按照这种方式进行sorting和显示,通常我会使用一个关系谓词作为惯例,但是对于一组数据有三个实体似乎是不合逻辑的。

您不需要针对每个材料,类别和子类别使用三种不同的NSMO。 您只需要一个具有这些属性类别,子类别和说明的材料的NSMO。

在ViewController中显示类别1:

 NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Materials"]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Materials" inManagedObjectContext:self.managedObjectContext]; // Required! Unless you set the resultType to NSDictionaryResultType, distinct can't work. // All objects in the backing store are implicitly distinct, but two dictionaries can be duplicates. // Since you only want distinct Categories, only ask for the 'Category' property. fetchRequest.resultType = NSDictionaryResultType; fetchRequest.propertiesToFetch = [NSArray arrayWithObject:[[entity propertiesByName] objectForKey:@"Category"]]; fetchRequest.returnsDistinctResults = YES; // Now it should yield an NSArray of distinct values in dictionaries. NSArray *dictionaries = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil]; NSLog (@"names: %@",dictionaries); 

有了这个,你可以从核心数据获取所有的材料NSManagedObjects不同的类别。

在ViewController 2中显示SubCategories:

 NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Materials"]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Materials" inManagedObjectContext:self.managedObjectContext]; NSPredicate * predicate = [NSPredicate predicateWithFormat:@"SELF.category == %@", selectedCategoryName]; fetchRequest.predicate = predicate; // Required! Unless you set the resultType to NSDictionaryResultType, distinct can't work. // All objects in the backing store are implicitly distinct, but two dictionaries can be duplicates. // Since you only want distinct SubCategory, only ask for the 'SubCategory' property. fetchRequest.resultType = NSDictionaryResultType; fetchRequest.propertiesToFetch = [NSArray arrayWithObject:[[entity propertiesByName] objectForKey:@"SubCategory"]]; fetchRequest.returnsDistinctResults = YES; // Now it should yield an NSArray of distinct values in dictionaries. NSArray *dictionaries = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil]; NSLog (@"names: %@",dictionaries); 

有了这个,你可以从核心数据获取所有的材料NSManagedObjects不同的类别。

对于第三个Viewcontroller列出所有属于Selected类别和子类别的项目,请使用:

 NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Materials"]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Materials" inManagedObjectContext:self.managedObjectContext]; NSPredicate * predicate = [NSPredicate predicateWithFormat:@"SELF.category == %@ and SELF.subcategory == %@", selectedCategoryName,selectedSubcatgory]; fetchRequest.predicate = predicate; // Required! Unless you set the resultType to NSDictionaryResultType, distinct can't work. // All objects in the backing store are implicitly distinct, but two dictionaries can be duplicates. // Now it should yield an NSArray of distinct values in dictionaries. NSArray *dictionaries = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil]; NSLog (@"names: %@",dictionaries); 

A.有三个实体没有错。 对于一组数据,您没有三个实体。 对于一组数据(材料),您将有一个实体(材料),一个实体用于另一组数据(子类别),另一个实体用于另一组数据(类别)。 (更确切地说,对于三种types的数据集,您将有三种实体types )。

将结构build模成不同的实体types并不意味着你放弃了材料的数据集。 你还有这个。

http://en.wikipedia.org/wiki/Second_normal_form

B.但是,如果你想拥有属性而不是关系,你必须做到这一点。

假设类别和子类别是通过名称来标识的。 (这是另一个错误,但这个错误是第一个错误的结果。)

您必须将在第一个视图控制器中select的类别的名称传递给第二个。 然后你可以使用这个名字构build谓词:

 NSPredicate * predicate = [NSPredicate predicateWithFormat:@"category == %@", self.passedName]; 

如果你想坚持categorysubcategory作为属性而不是关系,另一个select是使用NSFetchedResultsControllers来为你导出不同的值。

在你的第一个tableViewController中,指定category作为FRC的sectionNameKeyPath 。 然后在你的table view数据源方法中,使用FRC的sections属性填充你的tableView和单元格。 例如,

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[self.fetchedResultsController sections] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][indexPath.row]; cell.textLabel.text = sectionInfo.name return cell; } 

其他代理/数据源方法等等。

同样,在第二个表视图控制器中,您将包含一个谓词来限制对具有相关category材质的提取,并将FRC的sectionNameKeyPath指定为subcategory 。 然后使用与上面相同的技巧来填充FRC中的部分数据(在这种情况下将是子类别)中的单元格。

最后,在你的第三个表视图控制器中,只需使用一个谓词来将结果限制到相关的categorysubcategory ,并以正常的方式实现FRC和tableView委托/数据源方法。