按翻译后的属性对对象排序
Sort objects by translated properties
我有一个 returns 具有英语属性的对象的提取请求。我想根据 NSLocalizedString
上的翻译(俄语)等价物对这些对象进行排序。我的代码错误地返回按英语排序的数据。我正在使用以下排序描述符:
[NSSortDescriptor sortDescriptorWithKey:@"category"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)]]];
我的核心数据实体名为 Good
,具有 category
和 name
属性。我想要一个排序描述符数组,我可以将其传递给获取控制器 (setSortDescriptors:
),它将首先按翻译类别排序,然后按翻译名称排序。
如果语言环境是英文且英文单词排序没问题。但是当语言环境是俄语或乌克兰语时,这种排序不起作用。这是俄语语言环境的排序数组的输入
Кулеры
Кулеры
Память
Память
Микрофоны
Блоки питания
Блоки питания
Звуковые карты
Видеокарты
Видеокарты
这是错误的。我做错了什么?谢谢!
更新 1:我正在测试它
for (int i = 0; i < sortedArray.count; i++)
{
NSLog(@"%@", NSLocalizedString([[sortedArray objectAtIndex: i] category], nil));
}
更新二,完整代码
- (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;
}
使用 localizedCaseInsensitiveCompare:
只是意味着在考虑一个给定的字符串是否小于另一个时(即,“Ф”和“ф”是否等同于 "case insensitive" 目的)时将参考语言环境。它不会导致系统为您调用 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
然后您可以对这些翻译后的属性进行排序和显示。我喜欢这种方法,因为我认为它使代码非常清晰,并且意味着您可以实现缓存或任何您想要的东西,或者添加其他 属性-specific 逻辑。也就是说,有时您可能希望能够根据翻译进行排序。或者你可能有很多这样的东西并且想避免创建大量的样板文件(或花哨的方法转发技巧)。
在这种情况下,您可以将自定义排序描述符与您自己的比较规则结合使用。对于简单的 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]
和return基于翻译版本的顺序。这样,我们可以使用以下排序描述符:
NSArray *sortDescriptors =
@[
[NSSortDescriptor sortDescriptorWithKey:@"category" ascending:YES selector:@selector(my_translatedCaseInsensitiveCompare:)],
[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(my_translatedCaseInsensitiveCompare:)],
];
我有一个 returns 具有英语属性的对象的提取请求。我想根据 NSLocalizedString
上的翻译(俄语)等价物对这些对象进行排序。我的代码错误地返回按英语排序的数据。我正在使用以下排序描述符:
[NSSortDescriptor sortDescriptorWithKey:@"category"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)]]];
我的核心数据实体名为 Good
,具有 category
和 name
属性。我想要一个排序描述符数组,我可以将其传递给获取控制器 (setSortDescriptors:
),它将首先按翻译类别排序,然后按翻译名称排序。
如果语言环境是英文且英文单词排序没问题。但是当语言环境是俄语或乌克兰语时,这种排序不起作用。这是俄语语言环境的排序数组的输入
Кулеры
Кулеры
Память
Память
Микрофоны
Блоки питания
Блоки питания
Звуковые карты
Видеокарты
Видеокарты
这是错误的。我做错了什么?谢谢!
更新 1:我正在测试它
for (int i = 0; i < sortedArray.count; i++)
{
NSLog(@"%@", NSLocalizedString([[sortedArray objectAtIndex: i] category], nil));
}
更新二,完整代码
- (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;
}
使用 localizedCaseInsensitiveCompare:
只是意味着在考虑一个给定的字符串是否小于另一个时(即,“Ф”和“ф”是否等同于 "case insensitive" 目的)时将参考语言环境。它不会导致系统为您调用 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
然后您可以对这些翻译后的属性进行排序和显示。我喜欢这种方法,因为我认为它使代码非常清晰,并且意味着您可以实现缓存或任何您想要的东西,或者添加其他 属性-specific 逻辑。也就是说,有时您可能希望能够根据翻译进行排序。或者你可能有很多这样的东西并且想避免创建大量的样板文件(或花哨的方法转发技巧)。
在这种情况下,您可以将自定义排序描述符与您自己的比较规则结合使用。对于简单的 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]
和return基于翻译版本的顺序。这样,我们可以使用以下排序描述符:
NSArray *sortDescriptors =
@[
[NSSortDescriptor sortDescriptorWithKey:@"category" ascending:YES selector:@selector(my_translatedCaseInsensitiveCompare:)],
[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(my_translatedCaseInsensitiveCompare:)],
];