显示核心数据:如果属性具有相同的名称显示一次
我已经看过许多谓词问题,我已经阅读了文档,没有什么东西似乎跳出来作为我的问题的答案。
我有一个名为材料的核心数据实体,我有属性类别 , 子类别和说明 。
我有三个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];
如果你想坚持category
和subcategory
作为属性而不是关系,另一个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中的部分数据(在这种情况下将是子类别)中的单元格。
最后,在你的第三个表视图控制器中,只需使用一个谓词来将结果限制到相关的category
和subcategory
,并以正常的方式实现FRC和tableView委托/数据源方法。
- 核心数据:,这个方法会反映对象的变化吗?
- 对于在主线程的appDelegate managedObjectContext中创build的对象,“核心数据无法完成错误”
- 如果应用程序在10秒内死亡,NSUserDefaults丢失新保存的数据
- 核心数据对象在不同的tableView部分
- 如何使用predicateWithFormat进行查询NSString包含在NSSet中
- 为什么这段代码引起“CoreData:error:(19)PRIMARY KEY必须是唯一的”错误?
- 核心数据与iCloud导致低内存警告和崩溃,内存使用量不断增长
- 核心数据线程和locking争用问题
- 核心数据ios9:多字段唯一约束