Displaying Core Data: If attribute has same name display once

余生长醉 提交于 2019-12-06 12:29:01

You need not three different NSMO for each Materials, Category and Sub category. You only need one NSMO that is Materials which has these Attributes category, subcategory and description.

For Showing Categories in 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);

With this you can fetch all the Materials NSManagedObjects with distinct categories from Core data.

For Showing SubCategories in 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);

With this you can fetch all the Materials NSManagedObjects with distinct categories from Core data.

For third Viewcontroller to list all the items belong to a Selected category and subcategory use:

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. There is nothing wrong in having three entities. You do not have three entities for one set of data. You would have one entity (Material) for one set of data (materials), one entity for another set of data (subcategories) and one entity for another set of data (categories). (To be more precise: you would have three entity types for three types of data sets).

Modelling the structure into different entity types does not mean that you give up the data set of materials. You still have that.

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

B. However, if you want to have attributes instead of relationships you have to do that different.

Let's say that the category and subcategory are identified by its name. (This is another mistake, but this mistake is the consequence of the first one.)

You have to pass the name of the category selected in the first view controller to the second one. Then you can build the predicate using that name:

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

If you want to stick with category and subcategory as attributes rather than relationships, another option would be to use the NSFetchedResultsControllers to derive the distinct values for you.

In your first tableViewController, specify category as the sectionNameKeyPath for the FRC. Then in your table view datasource methods, use the FRC's sections property to populate your tableView and cells. For example,

- (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;
}

And so on for other delegate/datasource methods.

Likewise in your second table view controller, you would include a predicate to restrict the fetch to those Materials with the relevant category, and specify the FRC's sectionNameKeyPath as subcategory. Then use the same trick as above to populate the cells with the section data (which will in this case be the subcategories) from the FRC.

Finally, in your third table view controller, just use a predicate to restrict the results to the relevant category and subcategory and implement the FRC and tableView delegate/datasource methods in the normal way.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!