"localizedStandardCompare" depends on the language preference of the iOS device - ios

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES selector:#selector(localizedStandardCompare:)];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor,nil]];
I am working on an app that has a list of names, where all names are in Íslenska(Icelandic) language.
The above code works fine if the language selected for apps in settings is Íslenska(Icelandic) but the sort descriptor fails if the language is other than Íslenska(Icelandic).
Is there any way to resolve this dependency problem?

This should create a sortDescriptor that will compare strings using is_IS locale.
NSSortDescriptor* sortDescriptior =[[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES comparator:^(NSString* str1, NSString* str2) {
static NSStringCompareOptions comparisonOptions =
NSCaseInsensitiveSearch | NSNumericSearch |
NSWidthInsensitiveSearch | NSForcedOrderingSearch;
return [str1 compare:str2 options:comparisonOptions range:NSMakeRange(0, str1.length) locale:[NSLocale localeWithLocaleIdentifier:#"is_IS"]];
}];

Related

Sort on string and float not working

I have name and distance fields in an array of data that I want to sort; I can sort by either one but not both together. I want the data sorted by name first, then distance, but when I use the two together, the sort is always on the first descriptor in the list, the second seems to get ignored.
NSSortDescriptor *nameSort = [[NSSortDescriptor alloc]
initWithKey:#"NAME"
ascending:YES
selector:#selector(localizedStandardCompare:)];
NSSortDescriptor *distanceSort = [[NSSortDescriptor alloc]
initWithKey:#"DISTANCE"
ascending:YES];
sortedArray = [featureSet.features sortedArrayUsingDescriptors:#[nameSort, distanceSort]];
[super.tableView reloadData];
The behavior you're seeing definitely makes sense - "A&W #0338" comes before "A&W #0339", so there is nothing more for the distance sort to determine.
If all of your data is structured this way - a name followed by #000 - you can strip the numbers off for your sort, and then your distance sort can do its job. You can either do that at the model layer by splitting your title into two properties, a name and location number, or you can do it inside of a sort descriptor.
NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:#"title" ascending:YES comparator:^NSComparisonResult(NSString *str1, NSString *str2) {
NSString *title1 = [[str1 componentsSeparatedByString:#" #"] firstObject];
NSString *title2 = [[str2 componentsSeparatedByString:#" #"] firstObject];
return [title1 compare:title2];
}];
If you use this nameSort and your distanceSort, "A&W #0338", "25 km" will come after "A&W #0339"

Sort NSArray of NSDictionaries ignore case

I am sorting an NSArray of NSDictionaries which is working using the following code
NSArray *getIndexArray = [nicknamesCombinedArray copy];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"MANUFACTURER" ascending:YES];
NSDictionary *sortedGetIndexArray = [getIndexArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
The only issue is that when it sorts if the word is all CAPS then it sorts like this
JESS
Jack
Jelly
Job
Where I would like it to be
Jack
Jelly
JESS
Job
Try this code..
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"MANUFACTURER" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];

Equal Core Data statement to SQLite statement (order by ... desc..)

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

NSSortDescriptor with two equally important keys

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.

setting multiple sort descriptors

I have a array of objects and need to sort it by rating and after by number of votes descendent(so that if two 5 stars rated elements compare, the one with the most votes should be first)
Is it possible to sort a NSArray by two descriptors:first after rating and then after votes count?
I've found on http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSSortDescriptor_Class/Reference/Reference.html
something like sortUsingDescriptors: but i can't find it anywhere in the docs, think it's deprecated.
Yes you can:
NSSortDescriptor *sortRating = [[NSSortDescriptor alloc] initWithKey:#"rating" ascending:NO];
NSSortDescriptor *sortVotes = [[NSSortDescriptor alloc] initWithKey:#"votes" ascending:NO];
NSArray *sortedArray = [orignalAray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortRating, sortVotes, nil]];
[sortRating release], sortRating = nil;
[sortVotes release], sortVotes = nil;
You are basically right. On NSArray there is the
- (NSArray *)sortedArrayUsingDescriptors:(NSArray *)sortDescriptors
method. This will return a new array, sorted according to various descriptors.
- (void)sortUsingDescriptors:(NSArray *)sortDescriptors
does exist, but is on NSMutableArray, which might explain why you couldn't find it in the documentation for NSArray. It accomplishes the same goal, but sorts the array you call it on, rather than returning a new array. Neither is deprecated.
Here's a one-liner.
NSArray *sortedArray = [unsortedArray sortUsingDescriptors:[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey#"rating" ascending:NO], [NSSortDescriptor sortDescriptorWithKey#"date" ascending:NO], nil]];
Use - (NSArray *)sortedArrayUsingDescriptors:(NSArray *)sortDescriptors. Here is the documentation: NSArray Class Reference
E.g:
NSSortDescriptor *sortRating = nil;
NSSortDescriptor *sortDate = nil;
NSSortDescriptor *sortRating = [[NSSortDescriptor alloc] initWithKey:#"rating" ascending:NO];
NSSortDescriptor *sortDate = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:NO];
NSArray *sortedArray = [auxArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortRating,sortDate,nil]];
[sortRating release];
sortRating = nil;
[sortDate release];
sortDate = nil;
Cheers!
If you have one NSArray use this one:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"x_date" ascending:TRUE];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"x_time" ascending:TRUE];
[tempArray sortUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor,sortDescriptor1, nil]];

Resources