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
There're two approaches I can think of:
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.
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];
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With