使用iPhone的排序描述符对核心数据位置更改进行排序

时间:2011-06-30 13:03:21

标签: iphone objective-c sorting core-data nssortdescriptor

我有一个具有两个属性的CoreData实体。一个称为“位置”,另一个称为“positionChange”。它们都是整数,其中position属性是当前位置,positionChange是前一个位置和新位置之间的差值。这意味着positionChange可以是负数。

现在我想按positionChange排序。但我希望它忽视负面价值观。目前我正在将它降序排序,这将得到结果:2,1,0,-1,-2。 但我正在寻找的是得到这个结果:2,-2,1,-1,0。

有关如何使用排序描述符解决此问题的任何想法?


修改

我有2个类,一个叫做DataManager,另一个包含我的NSNumber类别(positionChange属于NSNumber类型)。

在DataManager中,我有一个名为'fetchData:'的方法,其中我正在使用排序描述符执行我的获取请求:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Entity" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"positionChange" ascending:NO selector:@selector(comparePositionChange:)];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

我正在为请求做更多的事情,但这对这个问题并不感兴趣。

我的NSNumber类别应与您发布的类别完全相同: 在.h:

@interface NSNumber (AbsoluteValueSort)
- (NSComparisonResult)comparePositionChange:(NSNumber *)otherNumber;
@end

在.m:

@implementation NSNumber (AbsoluteValueSort)

- (NSComparisonResult)comparePositionChange:(NSNumber *)otherNumber
{
    return [[NSNumber numberWithFloat:fabs([self floatValue])] compare:[NSNumber numberWithFloat:fabs([otherNumber floatValue])]];
}

@end

当我在我的DataManager对象上调用fetchData时,出现此错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'unsupported NSSortDescriptor selector: comparePositionChange:'

关于可能是什么情况的任何想法?我在我的DataManager类中包含了我的NSNumber类头文件。

2 个答案:

答案 0 :(得分:5)

代码因unsupported NSSortDescriptor selector错误而失败的原因是您正在使用SQLite数据存储并尝试使用Cocoa方法作为排序描述符。使用SQLite存储,排序描述符可以即时转换为SQL,并由SQLite进行排序。这确实有助于提高性能,但这也意味着排序是在非Cocoa环境中完成的,而自定义比较方法不存在。像这样的排序仅适用于常见的已知方法,而不适用于任意Cocoa代码。

一个简单的解决方法是在不进行排序的情况下进行获取,获取结果数组并对其进行排序。可以使用您想要的任何Cocoa方法对数组进行排序,因此med200的类别应该在那里很有用。

如果您的数据集不是很大,您也可以从SQLite数据存储更改为二进制存储。

答案 1 :(得分:2)

试试这个,假设你的positionChange是一个NSNumber:

@interface NSNumber (AbsoluteValueSort)

-(NSComparisonResult) comparePositionChange:(NSNumber *)otherNumber;

@end

接下来是:

@implementation NSNumber (AbsoluteValueSort)

-(NSComparisonResult) comparePositionChange:(NSNumber *)otherNumber
{
    return [[NSNumber numberWithFloat: fabs([self floatValue])] compare:[NSNumber numberWithFloat: fabs([otherNumber floatValue])]];
}

@end

然后执行此操作:

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"positionChange" ascending:NO selector:@selector(comparePositionChange:)];

并使用该描述符排序。如果你想使-2总是在2之后,或者5总是在-5之后你可以修改comparePositionChange:在一个数字是另一个数字的负数的情况下返回NSOrderedAscending。