简体   繁体   中英

Filter hierarchy

I'm writing an application with Core Data that have to maintain a catalog with 4 levels of hierarchy.

Category <--->> SubCategory <--->> Item <--->> SubItem

I have a screen (table/collection view) where Items are displayed along with Category and SubCategory titles. The Items could be. Basically I have to display filtered catalog. Let's say Item have a name and I want to filter items by name.

Example.

Category: Category 1
  SubCategory: SubCategory 1.1
    Items: [aaa, bbb, ccc, abc, abd, abg] 
  SubCategory: SubCategory 1.2
    Items: [aaa, bbb, ccc] 
Category: Category 2
  SubCategory: SubCategory 2.1
    Items: [123ab, 456ab, 123, 345, 456]

After filtering with query 'ab' I want to see the following objects:

Category: Category 1
  SubCategory: SubCategory 1.1
    Items: [abc, abd, abg] 
Category: Category 2
  SubCategory: SubCategory 2.1
    Items: [123ab, 456ab]

The thing is: I can't use fetch request against Category because it will only show me categories that contain items that satisfy criteria but it will not filter items. I can directly fetch filtered collection of Item but I have to rebuild structure Category - SubCategory - Item and put it in some arrays/dictionaries etc.

Is there a better way to filter deeply nested hierarchy with CoreData? The main question: is there a way to fetch leafs of deeply nested object tree while running fetch request against its root?

You can filter items using searchString by,

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]initWithEntityName:@"Item"];
NSPredicate *predicate = nil;

 if([_searchBar.text length] > 0){
    predicate = [NSPredicate predicateWithFormat:@"itemName CONTAINS[cd] %@", _searchBar.text];
}

if(predicate){
    [fetchRequest setPredicate:predicate];
}

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"itemName" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

If you need to sort the result by considering category and subCategory , you can use more sort descriptors according to your priority like,

NSSortDescriptor *sortDescriptorCategory = [[NSSortDescriptor alloc]initWithKey:@"categoryName" ascending:YES];
NSSortDescriptor *sortDescriptorSubCategory = [[NSSortDescriptor alloc]initWithKey:@"subCategoryName" ascending:YES];
NSSortDescriptor *sortDescriptorItem = [[NSSortDescriptor alloc]initWithKey:@"itemName" ascending:YES];

[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptorCategory, sortDescriptorSubCategory, sortDescriptorItem, nil]];

You can just separate each key with a '.' like so...

NSSortDescriptor *sortDescriptorSubCategory = [[NSSortDescriptor alloc]initWithKey:@"Category.SubCategory.Items" ascending:YES];

then, in iOS 7 +

[YOUR_ARRAY sortedArrayUsingDescriptors:@[sortDescriptorSubCategory]];

Or, older iOS versions

[YOUR_ARRAY sortedArrayUsingDescriptors:[NSArray sortDescriptorSubCategory, nil]];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM