2015-03-30 2 views
2

У меня есть запрос на выборку, который возвращает объекты с английскими свойствами. Я хочу сортировать эти объекты на основе их переведенных (русских) эквивалентов, используя на NSLocalizedString. Мой код неправильно возвращает данные, отсортированные так, как если бы это был английский. Я использую следующий дескриптор сортировки:Сортировать объекты по переведенным свойствам

[NSSortDescriptor sortDescriptorWithKey:@"category" 
           ascending:YES 
           selector:@selector(localizedCaseInsensitiveCompare:)]]]; 

сущность Мои основных данных называется Good с category и name свойствами. Мне нужен массив дескрипторов сортировки, который я могу передать контроллеру выборки (setSortDescriptors:), который сортирует сначала по переводимой категории, а затем по переводу имени.


Если язык является английским, а слова на английском языке сортируются в порядке. Но когда локаль является русской или украинской, эта сортировка не работает. Это uotput для отсортированного массива для русского языка

Кулеры 
Кулеры 
Память 
Память 
Микрофоны 
Блоки питания 
Блоки питания 
Звуковые карты 
Видеокарты 
Видеокарты 

и его не так. Что я делаю неправильно? Благодаря!

Update 1: Im тестирование его

for (int i = 0; i < sortedArray.count; i++) 
{ 

    NSLog(@"%@", NSLocalizedString([[sortedArray objectAtIndex: i] category], nil)); 
} 

Update 2, весь код

- (NSFetchedResultsController *) fetchedResultsController 
{ 
    if (_fetchedResultsController != nil) 
    { 
     return _fetchedResultsController; 
    } 
    NSManagedObjectContext *context = [self managedObjectContext]; 

    NSFetchRequest *goodsFetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *goodsEntity = [NSEntityDescription entityForName:@"Goods" inManagedObjectContext:context]; 

    [goodsFetchRequest setEntity: goodsEntity]; 
    NSError * error = nil; 

    NSArray * goods = [_managedObjectContext executeFetchRequest: goodsFetchRequest error:&error]; 

    NSSortDescriptor *categoryDescriptor = [[NSSortDescriptor alloc] initWithKey: @"category" ascending: YES ]; 
    NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey: @"name" ascending: YES selector: @selector(localizedCaseInsensitiveCompare:)]; 

    NSArray *sortedArray = [goods sortedArrayUsingDescriptors: 
          [NSArray arrayWithObject: 
          [NSSortDescriptor sortDescriptorWithKey: @"category" 
                  ascending:YES 
                  selector:@selector(localizedCaseInsensitiveCompare:)]]]; 




     NSLog(@"------"); 
     for (int i = 0; i < sortedArray.count; i++) 
     { 

      NSLog(@"%@", NSLocalizedString([[sortedArray objectAtIndex: i] category], nil)); 
     } 

    NSArray *sortDescriptors = @[categoryDescriptor, nameDescriptor]; 

    [goodsFetchRequest setSortDescriptors: sortDescriptors]; 


    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest: goodsFetchRequest managedObjectContext: context sectionNameKeyPath:@"category" cacheName: nil]; 

    _fetchedResultsController.delegate = self; 


    return _fetchedResultsController; 
} 
+0

Можете ли вы более точно узнать, как вы тестируете это? Я не могу воспроизвести это. Он сортирует Блоки питания, Блоки питания, Видеокарты, Видеокарты, Звуковые карты, ...(который, я считаю, верен) в моих тестах на Mac и iOS на английском и русском языках. Вы уверены, что вы выводите 'sortedArray', а не' товар'? –

ответ

3

Использование localizedCaseInsensitiveCompare: просто означает, что локаль будет консультироваться при рассмотрении вопроса одной заданной строки меньше, чем другое (т. е. являются ли «Ф» и «ф» эквивалентными для целей «без учета регистра»). Это не приводит к тому, что система вызывает NSLocalizedString для категории.

Моя предпочтительным решением было бы добавить переведенные свойства вашей модели объекта:

@interface Good (Translated) 
@property (nonatomic, readonly) NSString *translatedCategory; 
@property (nonatomic, readonly) NSString *translatedName; 
@end 

@implementation Good (Translated)  
- (NSString *)translatedCategory { 
    return NSLocalizedString(self.category, nil); 
} 

- (NSString *)translatedName { 
    return NSLocalizedString(self.name, nil); 
} 
@end 

Затем вы можете сортировать и отображать эти переведенные свойства. Мне нравится этот подход, потому что я думаю, что он делает код очень понятным и означает, что вы можете реализовать кэширование или что-то еще, если хотите, или добавить другую специфическую для свойства логику. Тем не менее, могут быть случаи, когда вы предпочитаете сортировать на основе перевода. Или, может быть, у вас их много, и вы хотите избежать создания тонны шаблонов (или причудливых методов переадресации).

В этом случае вы можете использовать собственный дескриптор сортировки с собственным правилом сравнения. Для простого NSArray вы можете использовать дескриптор сортировки на основе компаратора, но Core Data не поддерживает блоки, поэтому нам понадобится специальный селектор, который мы можем вызвать.

Что мы хотим, это функция сравнения, которая сравнивает переведенные строки. Мы можем сделать это, добавив категорию NSString так:

@interface NSString (MYTranslatedSorting) 
- (NSComparisonResult)my_translatedCaseInsensitiveCompare:(NSString *)other; 
@end 

@implementation NSString (MYTranslatedSorting) 

- (NSComparisonResult)my_translatedCaseInsensitiveCompare:(NSString *)other { 
    NSString *translatedSelf = NSLocalizedString(self, nil); 
    NSString *translatedOther = NSLocalizedString(other, nil); 
    return [translatedSelf localizedCaseInsensitiveCompare:translatedOther]; 
} 
@end 

Теперь можно назвать [englishString my_translatedCaseInsensitiveCompare:otherEnglish] и вернуть порядок, основанный на переведенный версию. При этом мы можем использовать следующие дескрипторы сортировки:

NSArray *sortDescriptors = 
@[ 
    [NSSortDescriptor sortDescriptorWithKey:@"category" ascending:YES selector:@selector(my_translatedCaseInsensitiveCompare:)], 
    [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(my_translatedCaseInsensitiveCompare:)], 
    ]; 
+0

Итак, массив 'товаров' фактически на английском или русском языке? Ваш «весь код» не соответствует вашему коду «Im testing it by». (Последний имеет в нем 'NSLocalizedString'.) Список, который вы дали, отсортирован по английскому (я думаю: охлаждающие вентиляторы, память, микрофоны ...), что заставляет меня думать, что« товар »на английском. –

+0

Извините, я отредактировал. Массив товаров на самом деле на английском языке, но у меня есть localizable.strings, где у меня есть перевод для всех слов. На самом деле я хочу использовать эту «категорию» в качестве имен разделов таблицы. – SergStav

+0

Право; вам просто нужно локализовать строки, прежде чем сравнивать их. См. Выше. –