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

Ios 显示核心数据:如果属性具有相同的名称,则显示一次,ios,objective-c,core-data,nspredicate,predicate,Ios,Objective C,Core Data,Nspredicate,Predicate,我看了很多谓词问题,我读了文档,似乎没有什么东西能回答我的问题 我有一个名为Materials的核心数据实体,还有属性类别、子类别和描述 我有三个UITableViewController,在每个UITableViewController中,我希望使用一个谓词来显示,如下所示: TableViewController 1:仅类别,不重复类别名称 选择一个类别并转到TableViewController 2 TableViewController 2:显示子类别不重复子类别名称 选择一个子类别并转

我看了很多谓词问题,我读了文档,似乎没有什么东西能回答我的问题

我有一个名为Materials的核心数据实体,还有属性类别、子类别和描述

我有三个UITableViewController,在每个UITableViewController中,我希望使用一个谓词来显示,如下所示:

TableViewController 1:仅类别,不重复类别名称

选择一个类别并转到TableViewController 2

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

选择一个子类别并转到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;

这是我第一次尝试以这种方式进行排序和显示,我通常会使用关系的谓词,这是一种常见的做法,但对于一组数据-材料,使用3个实体似乎不合逻辑

A.有三个实体没有什么错。一组数据没有三个实体。一个实体材质用于一组数据材质,一个实体用于另一组数据子类别,一个实体用于另一组数据类别。更准确地说:对于三种类型的数据集,您将有三个

将结构建模为不同的实体类型并不意味着放弃材质的数据集。你还有这个

然而,如果你想拥有属性而不是关系,你必须做不同的事情

假设类别和子类别由其名称标识。这是另一个错误,但这个错误是第一个错误的后果

必须将在第一个视图控制器中选择的类别的名称传递给第二个视图控制器。然后可以使用该名称构建谓词:

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

对于每个材料、类别和子类别,您不需要三个不同的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);
使用此功能,您可以从核心数据中获取具有不同类别的所有物料NSManagedObject

用于在ViewController 2中显示子类别:

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);
使用此功能,您可以从核心数据中获取具有不同类别的所有物料NSManagedObject

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

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);
如果您想坚持将类别和子类别作为属性而不是关系,另一个选项是使用NSFetchedResultsController为您派生不同的值

在第一个tableViewController中,将类别指定为FRC的sectionNameKeyPath。然后在表视图数据源方法中,使用FRC的sections属性填充表视图和单元格。比如说,

- (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;
}
对于其他委托/数据源方法,依此类推

同样,在第二个表视图控制器中,您将包括一个谓词,以将提取限制为具有相关类别的那些材质,并将FRC的sectionNameKeyPath指定为子类别。然后使用与上述相同的技巧,使用截面数据填充单元格,在本例中,截面数据将是FRC的子类别


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

这里有两个很好的答案,解决问题的方法正好相反。多实体一体机是更多的核心数据,可以更好地扩展,并在将来为您提供更多的灵活性。一体机实际上是您所要求的,并显示了一种有趣的技术,但它依赖于将所有内容提取到内存中,不允许您使用提取结果控制器。我两个都投了赞成票@jrturton同意这两个答案都很好。第二个陈述了更常见的答案和解决方案。然而第二个一针见血,我只需要在一个表中计算出它的实现,因为它显示的有点不同。谢谢你的反馈。嗨,这是一个很好的答案。我只有一些格式问题,但我明天会解决这些问题。谢谢你的回答。早上我会告诉你我是怎么做的。这个答案让我超越了“独特”和“群比”的限制;但是我还需要修改另外两个委托方法:我将numberOfSections委托方法设置为返回1,将titleForHeaderSection设置为返回nil。否则,我仍然拥有所有的部分,每个部分都有相同的内容——或者一个部分显示与第一个内容项匹配的标题。