Sorting Core Data Objects using NSFetchedResultsController - ios

I have two entities as follows
Item <----->> Categories
Each item may have multiple categories.
For e.g. There are 5 items each have a sort category as release_Date. I want to sort all these 5 items based on the release_Date with the table view header as the release_Date value of each item.
I want to sort these items based on the category value selected by the user from the popover. Also I want to display the sorted objects in a sectioned table view with the table header being the category values selected.
I am using nsfetchedresultscontroller for this. I am able to sort the items based on the name of the items. But I am finding no luck in sorting them using the relationship attribute.
Any kind of help is appreciable.

if i understand your model correctly you can do this with multiple sort descriptors pretty easily.
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:#"Categories.release_Date" ascending:NO];
NSArray *sortDescriptors = #[sortDescriptor1, sortDescriptor2];
[fetch setSortDescriptors:sortDescriptors];

Related

Need assistance regarding sorting NSMutableArray

I have an NSMutableArray and on every index I have another NSMutableArray but of different length like 2, 3, 4. I want to sort main array that the inside array who have bigger length come on top.
You can sort them using a descriptor:
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO];
[myArray sortUsingDescriptors:#[sd]];
The above code creates one sort descriptor on the property called "count" in descending order.
//Create a sort descriptor based on count using NSSortDescriptor class as-
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO];
//& sort your main array using sort descriptor
[mainArray sortUsingDescriptors:#[sortDescriptor]];

how to fetch result from core data sorted by the object creation date?

sorry if the title is not clear, i'll explain:
I have a note creation page, after creating a note I'm saving the note using the model class (nsmanagedobject sub class).
I have another table view controller which I'm showing the notes, and I want the notes on the table view to be sorted by creation date, is there a key for that?
this is what i have now:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"body" ascending:YES];
the key here is the text of the note so its sorted by the abc, can you help me to sort it by date?
tnx
There is no implicit creation date attribute for a managed object. You can create an attribute, say creationDate, in your model and set it to [NSDate date] when you create an object.
Then you can simply sort on this attribute
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"creationDate" ascending:YES];

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]];

Sort Database object

I have a UITableView each cell shows unique menu item I want items to be sort in my list but those menu items are not coming from an array but from a db object
Example:
cellForRowAtIndexPath{
Menus_Items *menuItem = [menuCategory.hasMenuItems.allObjects objectAtIndex:indexPath.row];
lblMenuItemName.text = menuItem.name;
}
How can I sort menu items ? I could have done it if it was an array i.e.
NSSortDescriptor *orderSort = [[NSSortDescriptor alloc] initWithKey:#"order" ascending:NO];
// String are alphabetized in ascending order
NSSortDescriptor *strNameSort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
// Combine the two
NSArray *sortDescriptors = #[orderSort, strNameSort];
arrCategories = [DatabaseHelper getAllData:#"Menus_cat" offset:0 predicate:[NSPredicate predicateWithFormat:#"ofOutlet == %#",outletsObject] sortDescriptor:nil];
// sortedArrayUsingDescriptor is the method use to sort an array which is having multiple parameters in sort descriptor
arrCategories = [arrCategories sortedArrayUsingDescriptors:sortDescriptors];
Help please. Thanks in advance
menuCategory.hasMenuItems.allObjects is an array so you can sort it to get the appropriate item. You could sort it each time or keep a sorted cache of the content. Neither of these options is ideal.
Really, you want to use a fetch request with a sort descriptor, ideally managed by a fetch request controller. Usually you would do that by using the relationship 'backwards'. So, you create the fetch and set the predicate to XXX = %#, where XXX is the relationship name and the supplied parameter is menuCategory.
This is assuming the relationship is 1:many, if it's many:many you will need a different predicate form.

Sort related entities in core data

I have two entities in my core data model. Author and Book. An author can have many books.
This is the part I've got sorted out. It's all working.
Now I'd like to fetch my authors in alphabetical order:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Author" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
No problems so far. But now I would like to fetch all the author's books, ordered by release date.
When I fetch the author's books using the following line of code …
self.selectedAuthor.books.allObjects
… the order of books seems to be completely random.
My question:
How can sort an object's related entities when fetching them from the core data, so that every time I use self.selectedAuthor.books.allObjects, all books are ordered by (for example) release date?
You can add a method - (NSArray *)booksSortedByDate; to the Author class interface and in the implementation write code like this:
- (NSArray *)booksSortedByDate {
return [self.books.allObjects sortedArrayUsingDescriptors:#[[NSSortDescriptor sortDescriptorWithKey:#"releaseDate" ascending:YES]]];
}
You can't. The to-many relationship books is represented by an NSSet, which is an
unordered collection. You can either
Get the array of all books self.selectedAuthor.books.allObjects as you did,
and then sort this array in memory,
or
Execute a fetch request on the Book entity with the predicate
[NSPredicate predicateWithFormat:#"author = %#", self.selectedAuthor]
to get only books of that author, and add a sort descriptor to the fetch request
to get the books sorted by release date.

Resources