Our DNA is written in Swift

NSArray Sorting

If you need the contents of an NSArray in a different order than they where entered into the array you have several options available. By far the simplest is to use descriptions if you have a standard data type you wish to sort by. You first set up an array with the names of fields to sort by. Then you sort.

// first you need to set up the descriptor
NSSortDescriptor *firstDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"firstField"
							 ascending:YES] autorelease];
NSSortDescriptor *secondDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"secondField"
							ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObjects:firstDescriptor, secondDescriptor, nil];
NSArray *unsortedObjects = [NSArray arrayWithObjects:oneObject, secondObject, nil];
// new and shiny sorted array
NSArray *sortedObjects = [unsortedObjects sortedArrayUsingDescriptors:sortDescriptors];

A little more involved but way more powerful is the method of using a selector. Here you add a function to your special class that you are keeping in the aray which takes care of deciding which of two object comes first: self or the other one.

Note that the sort method needs to be part of the class itself. You can make your sorting logic as complex as you like to using multiple sort methods. Cocoa Touch calls this method every time it needs to know the order of two objects. Having access to all the other object’s properties you can have your function return NSOrderedAscending, NSOrderedDescending or NSOrderedSame depending on what order you determine to be correct.

//  MyOwnClass sort function
- (NSComparisonResult)compareByTime:(MyOwnClass *)otherObject
	NSTimeInterval diff = [self.timestamp timeIntervalSinceDate:otherObject.timestamp];
	if (diff>0)
		return NSOrderedDescending;
	if (diff<0)
		return NSOrderedAscending;
	return NSOrderedSame;

Once you have it set up like this sorting is as easy as:

// original unsorted array
NSArray *unsortedObjects = [NSArray arrayWithObjects:oneObject, secondObject, nil];
// new and shiny sorted array
NSArray *sortedObjects = [unsortedObjects sortedArrayUsingSelector:@selector(compareByTime:)];

Here is another example that uses the compare method that’s built into NSString:

NSArray *unsortedArray = [NSArray arrayWithObjects:@"String3", @"String2", @"String1", nil];
NSArray *sortedArray = [unsortedArray sortedArrayUsingSelector:@selector(compare:)];

Sorting is very simple with the two methods shown above. If you just want simple sorting then use descriptors. If you need more control over the sorting method then define your own sorting method.

Categories: Recipes


  1. If any of this were “simple” why did you write a tutorial about it?