> ## Content Index
> Fetch the complete content index at: https://williamboles.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Sorting with Sort Descriptors
- URL: https://williamboles.com/multiple-sort-descriptors/
- Published: 2011-09-20T17:53:00.000Z
- Updated: 2026-09-26T16:34:36.000Z
- Description: Sorting is fundamental to any app. Here, we look at going beyond simple sorting with `NSSortDescriptor`.
- Author: William Boles
- Tags: Sorting

Sorting an array of `NSNumber` elements in Objective-C is fairly straightforward:

```
NSArray *unsortedArray = @[@(9), @(5), @(1), @(2), @(4)];
NSArray *sortedArray = [unsortedArray sortedArrayUsingSelector:@selector(compare:)];

NSLog(@"sortedArray: %@", sortedArray);
```

But what happens if we have something more complex, where the value being compared isn't the type itself but a property of that type?

The simple approach above won't work. Instead, we need to use a [NSSortDescriptor](https://developer.apple.com/documentation/foundation/nssortdescriptor?ref=williamboles.com). `NSSortDescriptor` allows us to sort the elements in an array based on that element's properties rather than the element itself.

![Photo of tea bags that have been sorted](https://storage.ghost.io/c/b9/b4/b9b42214-5933-4584-8e56-9ee8ca21d23b/content/images/size/w1000/2019/11/tee-bags-sorted-min-1.jpg)

Take the following class:

```
@interface WBWReview : NSObject

@property (nonatomic, assign) NSUInteger ratings;
@property (nonatomic, assign) NSUInteger votes;

@end

@implementation WBWReview

#pragma mark - Init

- (instancetype)initWithRatings:(NSUInteger)ratings votes:(NSUInteger)votes {
    self = [super init];
    
    if (self) {
        _ratings = ratings;
        _votes = votes;
    }
    
    return self;
}

@end
```

If we wanted to sort an array of `Review` instances by `ratings`, then we would configure a `NSSortDescriptor` instance like:

```
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"ratings" ascending:NO];

NSArray *sortedArray = [unsortedArray sortedArrayUsingDescriptors:@[sortDescriptor]]; 

NSLog(@"sortedArray: %@", sortedArray);
```

With the above code snippet, we configure an `NSSortDescriptor` instance to sort the `unsortedArray` using the `ratings` property of each element in that array, in descending order.

> If the elements of the array don't have a `ratings` property, then the above code would crash.

And if we wanted to sort by `votes`:

```
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"votes" ascending:NO];

NSArray *sortedArray = [unsortedArray sortedArrayUsingDescriptors:@[sortDescriptor]]; 

NSLog(@"sortedArray: %@", sortedArray);
```

Almost the same, the only thing that changed between the two examples is that the `key` of the `NSSortDescriptor` instance: from `ratings` to `votes`.

While sorting by one property is super, it's possible to combine `NSSortDescriptor` instances and sort by more than one property.

If instead we wanted to sort by `votes` and then `ratings`, then we would flip the order of the `NSSortDescriptor` instances when applied to the array:

```
NSSortDescriptor *ratingsSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"ratings" ascending:NO];
NSSortDescriptor *votesSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"votes" ascending:NO];

NSArray *sortedArray = [unsortedArray sortedArrayUsingDescriptors:@[ratingsSortDescriptor, votesSortDescriptor]];

NSLog(@"sortedArray: %@", sortedArray);
```

The above code snippet would sort `unsortedArray` first by `ratings` and then, if two (or more) `Review` instances had the same `ratings` value, by `votes`.

Straightforward stuff but super-powerful.