My table is populating using fetchedResultsController. I want to sort the data but conditionally on two things:
Name of users.
Scores.
a. If there is no score the table must to sorted with users name alphabetically.
b. If any user has score that must go on top.
I tried this
NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:#"userScore" ascending:NO];
NSSortDescriptor *sd2 = [[NSSortDescriptor alloc] initWithKey:#"displayName" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sd1, sd2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
It works fine but after app restart table is sorted only by user name.
Related
I'm using a statement in sqlite to select specific object from table:
NSString *statment = [NSString stringWithFormat:#"SELECT * FROM %# ORDER BY %# DESC LIMIT 1", TRAP_TABLE, DISTANCE_TO_CLOSE_POINT];
I want to do the same thing using core data.
How should I mix the NSPredicate & NSSortDescriptor in order to do the same?
EDIT:
This is what I did, didn't tried it yet:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:DISTANCE_TO_CLOSE_POINT ascending:NO selector:#selector(localizedCompare:)];
The NSPredicate is like the where clause of a SQL statement. Your example doesn't have a where clause.
In a NSFetchRequest you can add sort descriptors to handle the 'order by'. Also in the NSFetchRequest you can set a fetch limit.
From there you pass the NSFetchRequest to the NSManagedObjectContext and receive your results.
Update 1
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:DISTANCE_TO_CLOSE_POINT ascending:NO selector:#selector(localizedCompare:)];
That is overkill in this situation. I am guessing the value you are sorting on is a number which means you don't need localizedCompare: since you are not working with strings. So you can simplify it to:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:DISTANCE_TO_CLOSE_POINT ascending:NO];
And if you are in an ARC project, even reduce it down to:
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:DISTANCE_TO_CLOSE_POINT ascending:NO];
Which can then be thrown directly into the NSFetchRequest:
[fetchRequest setSortDescriptors:#[[NSSortDescriptor sortDescriptorWithKey:DISTANCE_TO_CLOSE_POINT ascending:NO]]];
I have a Core Data entity, MediaAsset. I have another called UploadAttempt which tracks all of the attempts we've made to upload that MediaAsset to our central server. I would like to fetch MediaAssets from the datastore ordered by the first UploadAttempt.
MediaAsset has 3 UploadAttempts, A, B, and C. UploadAttempt has an attemptDate attribute and I would like to find the earliest UploadAttempt for each MediaAsset and use that as the sorting.
I would like to create an NSSortDescriptor something along the lines of:
order by MediaAsset.uploadAttempts.attemptDate where attemptDate is the earliest attemptDate for that particular MediaAsset.
Does that make sense? Any help is appreciated.
(note: assume I cannot add an additional attribute to the MediaAsset. This is already existing data and I can't alter it.)
If I understand your question correctly, the following should work. If not, please ping me again, we will understand and correct it together.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"UploadAttempt"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityDesc];
NSError *error = nil;
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSArray *dateSortedAttempts = [self.managedObjectContext executeFetchRequest:fetchRequest
error:&error];
NSSet* mediaAssets= [NSSet setWithArray:[items valueForKeyPath:#"#distinctUnionOfObjects.MediaAsset"]];
I am constructing a NSFetchedResultsController for my entity, which has two attributes, let's say a shortName and a longName. All of the managed objects only have either the shortName or the longName.
How can I sort the objects based on both attributes (or rather the one which is not null) at the same time?
Clearly the following will not work in my case:
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"shortName" ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:#"longName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil];
It's quite interesting, but Im almost sure it is not possible to do. Just assigning shortName to the longName attribute, if there is no longName, while inserting to your db would be the best solution for me and simply sorting on longName.
I have an NSFetchRequest that is fetching an entity called "Player" and I want the results be sorted by 3 attributes in the following order:
Whether the attribute called "sendingoffOffence" is nil or not
Whether the relationship in the entity at "team.homeMatch" is nil or not
I want the strings in the "number" attribute to be sorted in ascending order.
Basically, I am looking to have all players that have a red card ("sendingOffOffence" is not nil) appear at the top of the list, then have the set be ordered by whether the player is on the home team or not, and then finally get the set of players on a team in an offense group be sorted by their jersey numbers.
As such, I use the following code in my fetch request:
// Set the entity for the fetch request
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Player"
inManagedObjectContext:self.match.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"match == %#", self.match];
[fetchRequest setPredicate:predicate];
// Sort the results
// Sort according to whether the user has a red card / sendingOffOffence
NSSortDescriptor *hasRedCard = [[NSSortDescriptor alloc] initWithKey:#"sendingoffOffence" ascending:NO];
// Sort according to whether the user is on the home team or not
NSSortDescriptor *isHomeTeam = [[NSSortDescriptor alloc] initWithKey:#"team.homeMatch" ascending:NO];
// Sort according to the player's jersey numbers
NSSortDescriptor *number = [[NSSortDescriptor alloc] initWithKey:#"number" ascending:YES selector:#selector(localizedStandardCompare:)];
[fetchRequest setSortDescriptors:#[hasRedCard, isHomeTeam, number]];
// Set the amount of records to retrieve from the database
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:self.match.managedObjectContext
sectionNameKeyPath:nil
cacheName:#"MatchCache"]
However, when I execute the above code, I get the following results:
This sorting order is wrong because I want the following order to appear in the red card section:
11 - Home
12 - Home
0 - Away
11 - Away
21 - Away
And in the yellow card section:
1 - Home
2 - Home
99 - Home
1 - Away
31 - Away
It looks like the yellow card section sorts correctly but the red card section is showing very weird behavior that makes it appear that it is not getting sorted at all.
I am fairly stumped as to why the red card section fails to sort correctly - any thoughts? Should I just sort these objects in memory instead of relying on core data to get my preferred order?
Please be aware that this is a core data application with a SQL backed persistence store.
UPDATE
The following is the SQL statement that core data is using in my fetch:
CoreData: annotation: fetch using NSSQLiteStatement <0x11c77cd0> on entity 'SPlayer' with
sql text 'SELECT t0.Z_ENT, t0.Z_PK FROM ZFSMANAGEDOBJECT t0 LEFT OUTER JOIN ZSTEAM t1 ON
t0.ZTEAM = t1.Z_PK WHERE ( t0.ZMATCH1 = ? AND t0.Z_ENT = ?) ORDER BY
t0.ZSENDINGOFFOFFENCE DESC, t1.ZHOMEMATCH DESC, t0.ZNUMBER COLLATE NSCollateFinderlike '
This is the line that is not being properly applied (for the RED card case):
NSSortDescriptor *isHomeTeam = [[NSSortDescriptor alloc] initWithKey:#"team.homeMatch" ascending:NO];
Without seeing your data model and some of the sample data, it's hard to say why this would not be sorting properly. I would assume this would put NIL values first, then proper values next (so sorting ascending NO would do what it's doing in the YELLOW card case).
If I was in this situation, I would check my assumptions about sort order and these team.homeMatch properties. Do a test where this is the only sort description.
Then focus in on what is different with the RED/YELLOW card condition.
We done without NSFetchedResultsController like this check it....
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Player"
inManagedObjectContext:self.match.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"match == %#", self.match];
[fetchRequest setPredicate:predicate];
// Sort the results
// Sort according to whether the user has a red card / sendingOffOffence
NSSortDescriptor *hasRedCard = [[NSSortDescriptor alloc] initWithKey:#"sendingoffOffence" ascending:NO];
// Sort according to whether the user is on the home team or not
NSSortDescriptor *isHomeTeam = [[NSSortDescriptor alloc] initWithKey:#"team.homeMatch" ascending:NO];
[fetchRequest setSortDescriptors:#[hasRedCard, isHomeTeam]];
// Set the amount of records to retrieve from the database
[fetchRequest setFetchBatchSize:20];
NSArray *resultArray = [self.match.managedObjectContext executeFetchRequest:request error:&error];
NSSortDescriptor *number = [[NSSortDescriptor alloc] initWithKey:#"number" ascending:YES selector:#selector(localizedStandardCompare:)];
NSArray *sortedArray = [resultArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:number, nil]];
I have an Agency entity that has a fetched property city. I'm performing a fetch request and I want my results to be sorted by agency's name and by city's name.
This is the part of old code. As you can see there was a relationship to the entity City and I could setup my sort descriptor easily. But now I've replaced relationship by fetched property.
Help me please, how I need to modify this code?
self.context = //...
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *callEntity = [NSEntityDescription entityForName:#"Agency" inManagedObjectContext:self.context];
[fetchRequest setEntity:callEntity];
NSSortDescriptor *sortByCityNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"city.name" ascending:YES selector:#selector(caseInsensitiveCompare:)];
NSSortDescriptor *sortByNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES selector:#selector(caseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByCityNameDescriptor, sortByNameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
//performing a fetch