Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Diacritic Sensitive sort for objects fetched from core data?

If I want to sort an array of items alphabetically without the option NSDiacriticInsensitiveSearch I need to use a NSSortDescriptor with comparator

 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"SortTitle" ascending:YES comparator:
                                        ^(id obj1, id obj2) {
                                            NSInteger options = NSCaseInsensitiveSearch
                                            | NSNumericSearch                    // Numbers are compared using numeric value
                                            //  | NSDiacriticInsensitiveSearch  // Ignores diacritics (â == á == a)
                                            | NSWidthInsensitiveSearch;        // Unicode special width is ignored

                                            return [(NSString*)obj1 compare:obj2 options:options];

However such NSSortDescriptor with comparator is not allowed to use in a NSFetchRequest. Therefore should I sort the results after fetching them from core data? Is this computationally expensive in terms of performance?

thanks

like image 862
aneuryzm Avatar asked Dec 27 '13 09:12

aneuryzm


1 Answers

There're two approaches I can think of:

  1. Therefore should I sort the results after fetching them from core data? - that's a one way of doing it. Apple doesn't provide exact string sorting complexities, but I think the bigger problem is the need to first fetch all objects from the persistent store. If you have a lot of data it can hinder the performance. It's best to profile it and only then decide if the performance is acceptable.

  2. You can try to use NSString methods which are translated into SQL: localizedStandardCompare:, localizedCompare: or localizedCaseInsensitiveCompare:. A sort descriptor using any of these methods can be created in the following way:

    sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sortTitle"
                                                   ascending:YES
                                                    selector:@selector(localizedCaseInsensitiveCompare:)];
    

    If none of these methods sorts the data the way you want, you can also preprocess it beforehand, e.g. when the title changes you remove the diacritics etc. (see Normalize User-Generated Content at NSHipster - CFStringTransform). UPDATE: Let me assume the title attribute is named title and the title for sorting is named sortTitle. In a subclass of NSManagedObject you can override didChangeValueForKey:as follows:

    - (void)didChangeValueForKey:(NSString *)key
    {
        [super didChangeValueForKey:key];
    
        if ([key isEqualToString:@"title"]) {
            NSString *cleanTitle = [self.title mutableCopy];
            CFStringTransform((__bridge CFMutableStringRef)(cleanTitle), NULL, kCFStringTransformStripCombiningMarks, NO);
            self.sortTitle = [cleanTitle copy];
        }
    }
    
like image 124
Arek Holko Avatar answered Sep 18 '22 20:09

Arek Holko