开发者

Sorting core data position changes with sort descriptors for iPhone

I have a CoreData entity with two attributes. One called 'position' the other called 'positionChange'. Both of them are integers where the position开发者_如何转开发 attribute is the current position and the positionChange is the difference between the previous position and the new position. This means that the positionChange can be negative.

Now I would like to sort by positionChange. But I would like it to disregard the negative values. Currently I'm sorting it descending, which will give the result: 2, 1, 0, -1, -2. But what I'm looking for is to get this result: 2, -2, 1, -1, 0.

Any ideas on how to solve this using sort descriptors?


EDIT

I got 2 classes, one called DataManager and the other containing my NSNumber category (positionChange is of type NSNumber).

In DataManager I have a method called 'fetchData:' where I'm executing my fetch request with a sort descriptor:

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]];

I'm doing some more stuff to the request, but that's not interesting for this issue.

My NSNumber category should be exactly like the one you posted: In the .h:

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

And in the .m:

@implementation NSNumber (AbsoluteValueSort)

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

@end

When I call fetchData on my DataManager object I get this error:

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

Any ideas of what might be the case? I have included my NSNumber category header file in my DataManager class.


The reason that code fails with the unsupported NSSortDescriptor selector error is that you're using a SQLite data store and attempting to use a Cocoa method as the sort descriptor. With a SQLite store, sort descriptors are translated on the fly into SQL and sorting is done by SQLite. That really helps performance but it also means that sorting is done in a non-Cocoa environment where your custom comparison method doesn't exist. Sorting like this only works for common, known methods and not for arbitrary Cocoa code.

A simple fix would be to do the fetch without sorting, get the results array, and sort that. Arrays can be sorted using whatever Cocoa methods you want, so med200's category should be useful there.

You could also change from a SQLite data store to a binary store, if your data set isn't very large.


Try this, assuming your positionChange is an NSNumber:

@interface NSNumber (AbsoluteValueSort)

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

@end

followed by:

@implementation NSNumber (AbsoluteValueSort)

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

@end

and then do this:

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

and sort with that descriptor. If you want to make it so that -2 is always after 2, or 5 is always after -5 you can modify comparePositionChange: to return NSOrderedAscending in the cases when one number is the negative of the other.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜