views:

411

answers:

2

Hi,

I have a NSArray of objects. Those objects have an int attribute called "distance". I would like to sort my array by distance.

Could someone please tell me how to do that ? I can't understand how the sortUsingSelector or sortUsingDescriptor methods are working...

Thanks

+8  A: 

I assume you're using an NSMutableArray, because an NSArray is immutable.

When you sort something, you want the end result to be arranged as

x1 <= x2 <= x3 <= x4 <= ... <= xN

How to define this <=? There are 3 solutions in ObjC.


1. -sortUsingSelector:

[arr sortUsingSelector:@selector(foo:)] means that its elements will be compared as*

x <= y      is equivalent to      [x foo:y] <= 0

For example, to sort a list of strings case-insensitively, you use [arr sortUsingSelector:@selector(caseInsensitiveCompare:)].


2. -sortUsingFunction:context:

This is similar to -sortUsingSelector:, but it uses a function pointer as input. [arr sortUsingFunction:funcptr context:ctx] means that its elements will be compared as

x <= y      is equivalent to      funcptr(x, y, ctx) <= 0

3. -sortUsingDescriptors:

This is the most complicated one. It takes a list of NSSortDescriptors which describe the expected order of the properties. One basic example:

NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"distance" ascending:YES];
[arr sortUsingDescriptors:[NSArray arrayWithObject:desc]];
[desc release];

the descriptor tells the sort routine to "sort by the key distance in ascending order".

Suppose there are 2 keys, integers x ascending then and strings y descending, then you may write

NSSortDescriptor* dx = [[NSSortDescriptor alloc] initWithKey:@"x" ascending:YES];
NSSortDescriptor* dy = [[NSSortDescriptor alloc] initWithKey:@"y" ascending:NO selector:@selector(caseInsensitiveCompare:)];
[arr sortUsingDescriptors:[NSArray arrayWithObjects:x, y, nil]];
[dx release];
[dy release];

and so on.


Note: * Actually you should only return -1, 0 or 1.

KennyTM
+1, except you don't return -1, 0, or 1. You return `NSOrderedDescending`, `NSOrderedSame`, or `NSOrderedAscending`.
Dave DeLong
A: 

Finnaly I found out how to do that :

after @implementation :

static NSInteger sort(Myclass *obj1, Myclass *obj2, void *context) {

if(obj1.distance < obj2.distance)
return NSOrderedAscending;
else if(obj1.distance > obj2.distance)
return NSOrderedDescending;
else
return NSOrderedSame;

Then wherever you need to sort your NSArray :

NSArray *sortedArray = [unsortedArray sortedArrayUsingFunction:sort context:NULL];
Yoot