5

I am sorting results of a fetch request with a sort descriptor.

NSFetchRequest* req = [[NSFetchRequest alloc] initWithEntityName:[MyEntity entityName]];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"property" 
                                                           ascending:YES 
                                                            selector:@selector(localizedCompare:)];
req.sortDescriptors = [NSArray arrayWithObject:descriptor];
return [self.managedObjectContext executeFetchRequest:req error:nil];

The problem is the words, which begins with non-english chars like 'İ' are listed at the end of the list. It is a turkish letter and the alphabet looks like this :

A, B, C, Ç, D, E, F, G, Ğ, H, I, İ, J, K, L, M, N, O, Ö, P, R, S, Ş, T, U, Ü, V, Y, Z.

So the letter is at 12th position.

I don't know why but using comparator after fetching objects works. So it works on any array but not with sort descriptor for fetch request.

Mert
  • 6,025
  • 3
  • 21
  • 33

3 Answers3

3

Take a look at the details of my question at NSFetchedResultsController v.s. UILocalizedIndexedCollation I show how to use the UILocalizedIndexedCollation to correctly generate the Alphabet and sort using the correct sort method based on the UILocalizedIndexCollation. My question just revolves around asking for a better way to do this.

If you dont use the UILocalizedIndexCollation you should only use the localizedStandardCompare: not localizedCompare as mentioned in the WWDC videos for localization.

Community
  • 1
  • 1
Brent Priddy
  • 3,817
  • 1
  • 24
  • 16
1

Try

[NSSortDescriptor alloc] initWithKey:@"property" ascending:YES selector:@selector(localizedCompare:)]

EDIT

@Mert has updated his question. It seems now that localizedCompare: sorts the turkish letters correctly, but does not work with the fetch request.

Here is what I have done to test this problem. Perhaps you can check if that works in your environment and then work from there:

// Create some entities:
NSArray *a = @[@"İ", @"J", @"Ğ", @"G", @"H", @"I", @"Ç", @"C"];
for (NSString *s in a) {
    MyEntity *e = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity"
                                                inManagedObjectContext:self.managedObjectContext];
    e.name = s;
}

// Fetch all entities in sorted order:
NSFetchRequest* req = [[NSFetchRequest alloc] initWithEntityName:@"MyEntity"];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"name"
                                                           ascending:YES
                                                            selector:@selector(localizedCompare:)];
req.sortDescriptors = [NSArray arrayWithObject:descriptor];
NSArray *result = [self.managedObjectContext executeFetchRequest:req error:nil];

"MyEntity" is a Core Data entity with one attribute "name" of type String.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • It didn't work. I also tried changing language of the simulator. – Mert Aug 05 '12 at 07:28
  • That is strange. If I sort an array with `[myArray sortedArrayUsingSelector:@selector(localizedCompare:)]` then I get correct results. Can you show the code how you setup the fetch request? – Martin R Aug 05 '12 at 08:19
  • I have done it in almost the same way (with a fetched results controller), and it works for german umlauts and other international characters. Btw: Do you compile with ARC or not? – Martin R Aug 05 '12 at 09:29
  • I already tried that but will ask again what was your Localization native development region in project settings? Yes I am compiling with ARC – Mert Aug 05 '12 at 09:38
  • Where does the localizedCompare function get the language? – Mert Aug 05 '12 at 09:41
  • 1. The Apple documentation on `localizedCompare:` is pretty vague on which localization it uses. For me it just worked. - 2. I do not set a "Localization native development region" in my project settings. The simulator Language is German and the Region is United States. – Martin R Aug 05 '12 at 11:49
  • To localize the problem you could fetch the results first and then create a sorted array with `NSArray *sortedResults = [results sortedArrayUsingSelector:@selector(localizedCompare:)]` - just to find out where the problem lies: the comparison function or the fetch request. – Martin R Aug 05 '12 at 11:52
  • Yes I edited my question and added that too. It works for array but not for a fetch request. Since I have like thousand entries, I am afraid of this may cause performance problems. – Mert Aug 05 '12 at 11:55
  • Is "property" a string attribute of your entity? – Martin R Aug 05 '12 at 11:57
0

I had a similar problems with :

[strArr sortedArrayUsingSelector:@selector(localizedCompare:)]

It seems that

localizedCompare

calls

compare:other options:nil range:NSMakeRange(0, self.length) locale: [NSLocale currentLocale]];

[NSLocale currentLocale] might be in a mixed state depending on the users preferences. It is therefor needed to create a clean NSLocale based on the users language

Try creating a category on NSString with the following content:

-(NSComparisonResult)currentLocalCompare:(id)other
{
    NSLocale * currLoc = [NSLocale currentLocale]; //get current locale
    NSLocale * loc = [[NSLocale alloc] initWithLocaleIdentifier:currLoc.localeIdentifier];//lets create a new clean NSLocale based on users prefared langauge
    return [self compare:other options:nil range:NSMakeRange(0, self.length) locale:loc];//compare using clean NSLocale
}

and call it like:

[strArr sortedArrayUsingSelector:@selector(currentLocalCompare:)]

EsbenB
  • 3,356
  • 25
  • 44