Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort non-english strings using nspredicate?

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.

like image 639
Mert Avatar asked Oct 07 '22 00:10

Mert


2 Answers

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.

like image 183
Brent Priddy Avatar answered Oct 13 '22 10:10

Brent Priddy


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.

like image 30
Martin R Avatar answered Oct 13 '22 11:10

Martin R