NSFetchedResultController - Custom Sorting on 2 Attributes - ios

I am using NSFetchedResultController in my Project. Following is a scenario i want to achieve.
I have a Table Called Contact in which i have have 2 attributes LastMessageDate and ContactName.
I want to sort Contact objects according to LastMessageDate. The objects which don't have LastMessageDate should be sorted according to ContactName (Alphabetically).
For Ex:
Consider i have C1,C2,C3,C4,C5,C6 as My Contact out of Which C2 and C6 have LastMessageDate Present. So the sorted Contacts should be C2,C6,C1,C3,C4,C5

use two sort descriptors first will sort all contact in alphabetic order and second will filter according to last message date. see following code -
NSSortDescriptor *contactName = [[NSSortDescriptor alloc]
initWithKey: #"ContactName" ascending: YES];
NSSortDescriptor *lastMessageDate = [[NSSortDescriptor alloc]
initWithKey: #"LastMessageDate" ascending: YES];
NSArray *sortedArray = [contactArray sortedArrayUsingDescriptors: [NSArray arrayWithObjects: contactName, lastMessageDate, nil]];

Can you set a default date for LastMessageDate, to either distantFuture or distantPast?
Now, when you sort by date these items will be first or last and the second sort descriptor will be used (hence they will be sorted alphabetically).
And your other code would check what the date is and not use when it is equal to distantFuture or distantPast (which could be in a custom accessor method).

Related

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.

Sorting Core Data Objects using NSFetchedResultsController

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

NSFetchedResultsController with sections sorted by TWO criteria

I have a table view that displays a musician's albums. Each section is an Album, each row is a Track. I need the albums/sections sorted by release date, then by title. I'm pulling the tracks from Core Data like so:
fetchRequest = [[NSFetchRequest alloc] init];
...
fetchRequest.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"album.releaseDate" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"album.title" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"trackNumber" ascending:YES],
nil];
frc = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context
sectionNameKeyPath:#"album.releaseDate" // <-- PROBLEM HERE
cacheName:nil];
This doesn't work because two albums with the same release date will appear in the same section.
If I use album.title as the sectionNameKeyPath, hell breaks loose because the sections are sorted alphabetically, then imposed on the tracks (which are sorted by date, title, trackNumber).
How do I sort the sections by date, then by title?
From what I've read, this single-property sorting is just something we have to live with on iOS. So I added a transient property to Album that acts as a sort key for both properties:
- (NSString *)sortKeyDateTitle
{
[self willAccessValueForKey:#"sortKeyDateTitle"];
NSString *sortKey = [NSString stringWithFormat:#"%#%#", self.releaseDate, self.title];
[self didAccessValueForKey:#"sortKeyDateTitle"];
return sortKey;
}
It produces strings like this:
1954-04-01 06:00:00 +0000A Night At Birdland, Vol. 1
1954-04-01 06:00:00 +0000A Night At Birdland, Vol. 2
It works, but converting from date to string for sorting seems stupid. I'm waiting for something better.

UITableView with Core Data ordered by time, not alphabetically

I'm working on an app that uses Core Data and a UITableView. What I've noticed is that when I add a new TableView entry, the cells seem to order alphabetically. Is there a way to make it so the cells are ordered by the time I add them (from top to bottom) rather than by the alphabet. Thanks!
You should add a timestamp field for your core data entity (type NSDate). Then, you can use a simple sort descriptor on your fetch request to sort the entities as appropriate.
For example, after you create the entity...
NSDate *now = [NSDate date];
[myNewEntity setValue:now forKey:#"timestamp"];
and then, in your fetch request...
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"MyEntity"];
NSSortDescriptor *sortByTimestamp = [NSSortDescriptor sortDescriptorWithKey:#"timestamp" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortByTimestamp];

Best way to sort an NSArray of NSDictionary objects?

I'm struggling with trying to sort an array of dictionaries.
My dictionaries have a couple of values of interest, price, popularity etc.
Any suggestions?
Use NSSortDescriptor like this..
NSSortDescriptor * descriptor = [[NSSortDescriptor alloc] initWithKey:#"interest" ascending:YES];
stories = [stories sortedArrayUsingDescriptors:#[descriptor]];
recent = [stories copy];
stories is the array you want to sort. recent is another mutable array which has sorted dictionary values. Change the #"interest" with the key value on which you have to sort.
All the best
[array sortUsingDescriptors:[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:#"YOUR-KEY" ascending:YES], nil]];
I don't really want to break it into multiple lines. It's already simple enough for me.
You can just traverse from the parent to the required child property. For e.g.
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"parent.child.child" ascending:YES];
Update , sortUsingDescriptors is now sortedArrayUsingDescriptors
So, its like:
items = [items sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
Write a sort function that compares the relevant fields in two dictionaries. When you have this version you can for example use NSArray#sortedArrayUsingFunction:context: to sort your array.
See NSArray Class Reference
array = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:#"YOUR-KEY" ascending:YES], nil]];
Remember assign to array

Resources