What I want to do seems pretty simple, but I can't find any answers on the web. I have an NSMutableArray of objects, and let's say they are 'Person' objects. I want to sort the NSMutableArray by Person.birthDate which is an NSDate.

I think it has something to do with this method:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

In Java I would make my object implement Comparable, or use Collections.sort with an inline custom comparator...how on earth do you do this in Objective-C?

23 Answers 11

Your Person objects need to implement a method, say compare: which takes another Person object, and return NSComparisonResult according to the relationship between the 2 objects.

Then you would call sortedArrayUsingSelector: with @selector(compare:) and it should be done.

There are other ways, but as far as I know there is no Cocoa-equiv of the Comparable interface. Using sortedArrayUsingSelector: is probably the most painless way to do it.

See the NSMutableArray method sortUsingFunction:context:

You will need to set up a compare function which takes two objects (of type Person, since you are comparing two Person objects) and a context parameter.

The two objects are just instances of Person. The third object is a string, e.g. @"birthDate".

This function returns an NSComparisonResult: It returns NSOrderedAscending if PersonA.birthDate < PersonB.birthDate. It will return NSOrderedDescending if PersonA.birthDate > PersonB.birthDate. Finally, it will return NSOrderedSame if PersonA.birthDate == PersonB.birthDate.

This is rough pseudocode; you will need to flesh out what it means for one date to be "less", "more" or "equal" to another date (such as comparing seconds-since-epoch etc.):

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

If you want something more compact, you can use ternary operators:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

Inlining could perhaps speed this up a little, if you do this a lot.

7 upvote
  flag
Using sortUsingFunction:context: is probably the most c-ish way and definitly the most unreadable one. – Georg Schölly
8 upvote
  flag
What's wrong with a "c-ish" approach? It works fine. – Alex Reynolds
11 upvote
  flag
There's nothing really wrong with it, but I think there are now much better alternatives. – Georg Schölly
5 upvote
  flag
Perhaps, but I don't think it would be any less readable to someone from a Java background who might be looking for something similar to Java's abstract Comparator class, which implements compare(Type obj1, Type obj2). – Alex Reynolds
upvote
  flag
I think the biggest stumbling block to using sortUsingFunction for some one with out a solid C background would be: a) realising it wants a function pointer; b) get used to the idea of a function pointer; c) parse the function pointer so as to construct the required function. – freespace
4 upvote
  flag
I get the sense a couple of you are looking for any reason whatsoever to criticize this perfectly fine answer, even if that criticism has very little technical merit. Weird. – Alex Reynolds
upvote
  flag
@Georg, the problem with your answer above, and the advantages to Alex's method here, is that you get one compare method per class. So if you need to compare on multiple criteria, you must use sortUsingFunction:content:, Right? – Dan Rosenstark
1 upvote
  flag
@Yar: Either you can use the solution I provided in the first paragraph, or you use multiple sort descriptors. sortedArrayUsingDescriptors: takes an array of sort descriptors as argument. – Georg Schölly
1 upvote
  flag
@Jeroen Hi! When you are going to reject an edit, just reject it, don't click "improve" if you don't actually mean to improve the edit. Rejecting the edits here was a good call, but by going through improve you've created two nonsensical revisions to the question. – yannis
upvote
  flag
I know, you are right, I had a moment of confusion here because of doing 3 things at once. Won't happen again ;) – JMoons
upvote
  flag
@Jeroen May I know why my edits are rejected? Just want to make sure what I am doing wrong here. thanks. – Walty Yeung
up vote 2172 down vote accepted

Compare method

Either you implement a compare-method for your object:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor (better)

or usually even better:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

You can easily sort by multiple keys by adding more than one to the array. Using custom comparator-methods is possible as well. Have a look at the documentation.

Blocks (shiny!)

There's also the possibility of sorting with a block since Mac OS X 10.6 and iOS 4:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

Performance

The -compare: and block-based methods will be quite a bit faster, in general, than using NSSortDescriptor as the latter relies on KVC. The primary advantage of the NSSortDescriptor method is that it provides a way to define your sort order using data, rather than code, which makes it easy to e.g. set things up so users can sort an NSTableView by clicking on the header row.

62 upvote
  flag
The first example has a bug: You compare the birthDate instance variable in one object with the other object itself, rather than its birthDate variable. – Martin Gjaldbaek
87 upvote
  flag
@Martin: Thanks! Funny that nobody else noticed before I got 75 upvotes for it. – Georg Schölly
74 upvote
  flag
Because this is the accepted answer, and therefore probably considered definitive by most users, it might be helpful to add a 3rd, block-based example so that users will be aware it exists too. – jpswain
6 upvote
  flag
@orange80: I tried that. I don't own a Mac any more, so it would be nice if you could look at the code. – Georg Schölly
4 upvote
  flag
You can also declare the parameters of the block with the correct type already, reducing the sorting to: [drinkDetails sortedArrayUsingComparator:^(Person* a, Person* b) { return [a.birthDate compare:b.birthDate]; }] – fishinear
upvote
  flag
@fishinear: Are you sure? I've haven't used blocks yet myself, but looking at other examples it seems that everyone uses id as the arguments. Example: Question 1, Question 2. – Georg Schölly
upvote
  flag
In the case where birthDate is null and you want those to show up at the end of the sorted array you can do this: NSDate *first = [(Person *)a birthDate] ? [a birthDate]:[NSDate distantFuture]; – TPoschel
upvote
  flag
so how about case insensitive sort on an nsstring object comparison using second method?? – Lithu T.V
upvote
  flag
@Lithu: Did you look at the documentation. It's basically directly in there. If you don't find out how to do it, ask in a new question. – Georg Schölly
upvote
  flag
@GeorgSchölly : yup worked it out by docs..frgt to update the cmnt :) – Lithu T.V
upvote
  flag
k here is the answer for wht i hav asked ,ie about case sensitive nd case insensitive sort.there is one more method in sort descriptor which defines the selector :- sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease]; – Lithu T.V
upvote
  flag
Thank you! That's a solution for issue about ordering accented characters in SQLite. – kubilay
11 upvote
  flag
If you have a NSMutableArray i prefer to use the methodes sortUsingDescriptors , sortUsingFunction or sortUsingSelector. As far as the array is mutable I usually don't need a sorted copy. – Stephan
upvote
  flag
I have used block option for sort. it's work great. but i have another problem i have to sort an array using condition. like i have two values "Company" and "Date". if the company name is same then it check date which would be latest it first sort can you help me out ? – Hiren
upvote
  flag
What if I have an array with latitude and longitude and I want to sort by distance from userLocation. I've calculated the distance to each. Do I create a new array with the distance value? – marciokoko
upvote
  flag
@marciokoko: Open a new questions, comments are not a good place for this. :) – Georg Schölly
upvote
  flag
1 upvote
  flag
Just wanted to add - the answer to the question asked by @HiRen isn't for another question. This is exactly what the sort descriptors in this example are for. Maybe this post should explain that you can use multiple sort descriptors to sort by many keys? – Accatyyc
upvote
  flag
@Accatyyc: I added a small paragraph about it. I didn't want to increase the complexity of the answer too much. – Georg Schölly
upvote
  flag
upvote
  flag
this should be updated to include literals, so future people looking at this code can see updated syntax, and how it's now being done. – Matthew Knippen
1 upvote
  flag
Not to beat a dead horse but its potentially be worth noting that sortedUsingComparator sorts in-place with a NSMutableArray, potentially a more common use case. – bcattle
upvote
  flag
And what is the best/fastest sorting method? – AlKozin
upvote
  flag
The third one is the best option? @GeorgSchölly – KarenAnne
upvote
  flag
@Karen: It depends. Use the compare method if there is a natural ordering between your objects. If it's a simple comparison, use a block. And finally if your comparison is tricky and uses lots of logic, an NSSortDescriptor probably makes the most sense. – Georg Schölly
upvote
  flag
I love the block as well, I've used it in a couple of projects I was working on, and they never failed me! Block to the rescue! :) ( and Georg ) – Septronic
upvote
  flag
Perfectly Explained. – Sid
upvote
  flag
Where does the compare method go? In the implementation of the custom object being sorted in the NSMutableArray, or in the implementation of the class doing the sorting? I sense it should be in the custom object's implementation (from the self.birthdate), but the formatting of the answer makes it seem like it's the same .m file as the call to sort the array, so I wanted to check to make sure. From the standpoint of a programming beginner, it's not obvious at all where to put snippets of code even if it might seem second nature to a vet. – Cindeselia
upvote
  flag
You're right, it goes into the implementation of the custom object. – Georg Schölly
upvote
  flag
For the first example, we need to declare the compare: method in the Person.h file to be used in other places? Is this example assuming that the sortedArrayUsingSelector: is going to be called within the Person.m file? – Lucas Chwe

There is a missing step in Georg Schölly's second answer, but it works fine then.

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptor:sortDescriptors];
upvote
  flag
The method call is actually "sortedArrayUsingDescriptors:", with an 's' at the end. – LucasTizma
upvote
  flag
Thanks, haven't seen that 's'. – Georg Schölly

For NSMutableArray, use the sortUsingSelector method. It sorts it-place, without creating a new instance.

upvote
  flag
Just an update: I too was looking for something that sorted the mutable array in place, there are now "sortUsing" equivalent methods for all the "sortedArrayUsing" methods as of iOS 7. Such as sortUsingComparator:. – jmathew

I tried all, but this worked for me. In a class I have another class named "crimeScene", and want to sort by a property of "crimeScene".

This works like a charm:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];

Starting in iOS 4 you can also use blocks for sorting.

For this particular example I'm assuming that the objects in your array have a 'position' method, which returns an NSInteger.

NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) 
{
    if ([obj1 position] > [obj2 position]) 
    { 
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 position] < [obj2 position]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

Note: the "sorted" array will be autoreleased.

I did this in iOS 4 using a block. Had to cast the elements of my array from id to my class type. In this case it was a class called Score with a property called points.

Also you need to decide what to do if the elements of your array are not the right type, for this example I just returned NSOrderedSame, however in my code I though an exception.

NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
    if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
        Score *s1 = obj1;
        Score *s2 = obj2;

        if (s1.points > s2.points) {
            return (NSComparisonResult)NSOrderedAscending;
        } else if (s1.points < s2.points) {
            return (NSComparisonResult)NSOrderedDescending;
        }
    }

    // TODO: default is the same?
    return (NSComparisonResult)NSOrderedSame;
}];

return sorted;

PS: This is sorting in descending order.

6 upvote
  flag
You don't actually need the "(Score *)" casts in there, you can just do "Score *s1 = obj1;" because id will happily cast to anything without warning from the compiler :-) – jpswain
upvote
  flag
right orange80 downcasting doesn't requires a cast before the weak variable. – thesummersign
upvote
  flag
Thanks guys, I've removed the cast from the answer – Chris
upvote
  flag
You should sort nil vs. not-nil to the top or bottom consistently, so the default end return might be return ((!obj1 && !obj2) ? NSOrderedSame : (obj1 ? NSOrderedAscending : NSOrderedDescending)) – Scott Corscadden
upvote
  flag
heh Chris, i tried this code, I do hv a refresh in my program.. for the first time i does correct job, got a descending order output.. but when i refresh.( execute the same code with same data ) it changed the order, it was not descending.. Say i hv 4 objects in my array, 3 hv same data, 1 is differed. – Nikesh K
upvote
  flag
If you actually expect objects that are not of the "Score" class, you need to sort them a bit more careful. Otherwise you have a situation where other == score1 < score2 == other which is inconsistent and could lead to trouble. You could return a value that implies Score objects sort before all other objects, and all other objects sort equal to each other. – gnasher729
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Thanks, it's working fine...

iOS 4 blocks will save you :)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html a bit of description

I've used sortUsingFunction:: in some of my projects:

int SortPlays(id a, id b, void* context)
{
    Play* p1 = a;
    Play* p2 = b;
    if (p1.score<p2.score) 
        return NSOrderedDescending;
    else if (p1.score>p2.score) 
        return NSOrderedAscending;
    return NSOrderedSame;
}

...
[validPlays sortUsingFunction:SortPlays context:nil];

Sorting NSMutableArray is very simple:

NSMutableArray *arrayToFilter =
     [[NSMutableArray arrayWithObjects:@"Photoshop",
                                       @"Flex",
                                       @"AIR",
                                       @"Flash",
                                       @"Acrobat", nil] autorelease];

NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease];

for (NSString *products in arrayToFilter) {
    if (fliterText &&
        [products rangeOfString:fliterText
                        options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0)

        [productsToRemove addObject:products];
}
[arrayToFilter removeObjectsInArray:productsToRemove];

If you're just sorting an array of NSNumbers, you can sort them with 1 call:

[arrayToSort sortUsingSelector: @selector(compare:)];

That works because the objects in the array (NSNumber objects) implement the compare method. You could do the same thing for NSString objects, or even for an array of custom data objects that implement a compare method.

Here's some example code using comparator blocks. It sorts an array of dictionaries where each dictionary includes a number in a key "sort_key".

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

The code above goes through the work of getting an integer value for each sort key and comparing them, as an illustration of how to do it. Since NSNumber objects implement a compare method, it could be rewritten much more simply:

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

or the body of the comparator could even be distilled down to 1 line:

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

I tend to prefer simple statements and lots of temporary variables because the code is easier to read, and easier to debug. The compiler optimizes away the temporary variables anyway, so there is no advantage to the all-in-one-line version.

-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}
upvote
  flag
why to pass in a mutable array, when a new array is returned. why to create a wrapper at all? – vikingosegundo

I have created a small library of category methods, called Linq to ObjectiveC, that makes this sort of thing more easy. Using the sort method with a key selector, you can sort by birthDate as follows:

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]
upvote
  flag
You ought to call it "LINQ to Objective-C". – Peter Mortensen

I just done multi level sorting based on custom requirement.

//sort the values

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec

upvote
  flag
+1 Just because this actually shows the returns values of the comparator. Thanks. – Pedrom
NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];

NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];

[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];

NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];

ForeignStockHolding *stockHoldingCompany;

NSLog(@"Fortune 6 companies sorted by Company Name");

    while (stockHoldingCompany = [enumerator nextObject]) {
        NSLog(@"===============================");
        NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
        NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
        NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
        NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
        NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
        NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
    }
    NSLog(@"===============================");
NSSortDescriptor  *sort = [[NSSortDescriptor alloc] initWithKey:@"_strPrice"
                                                 ascending:sortFlag selector:@selector(localizedStandardCompare:)] ;

You can use the following generic method for your purpose. It should solve your issue.

//Called method
-(NSMutableArray*)sortArrayList:(NSMutableArray*)arrDeviceList filterKeyName:(NSString*)sortKeyName ascending:(BOOL)isAscending{
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:sortKeyName ascending:isAscending];
    [arrDeviceList sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
    return arrDeviceList;
}

//Calling method
[self sortArrayList:arrSomeList filterKeyName:@"anything like date,name etc" ascending:YES];

Sort using NSComparator

If we want to sort custom objects we need to provide NSComparator, which is used to compare custom objects. The block returns an NSComparisonResult value to denote the ordering of the two objects. So in order to sort whole array NSComparator is used in following way.

NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
    return [e1.firstname compare:e2.firstname];    
}];

Sorts Using NSSortDescriptor
Let’s assume, as an example, that we have an array containing instances of a custom class, Employee has attributes firstname, lastname and age. The following example illustrates how to create an NSSortDescriptor that can be used to sort the array contents in ascending order by the age key.

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = @[ageDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

Sort using Custom Comparisons
Names are strings, and when you sort strings to present to the user you should always use a localized comparison. Often you also want to perform a case insensitive comparison. Here comes an example with (localizedStandardCompare:) to order the array by last and first name.

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

For reference and detailed discussion please refer: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html
http://www.ios-blog.co.uk/tutorials/objective-c/how-to-sort-nsarray-with-custom-objects/

In my case, I use "sortedArrayUsingComparator" to sort an array. Look at the below code.

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

Also my object is,

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end

Swift's protocols and functional programming makes that very easy you just have to make your class conform to the Comparable protocol, implement the methods required by the protocol and then use the sorted(by: ) high order function to create a sorted array without need to use mutable arrays by the way.

class Person: Comparable {
    var birthDate: NSDate?
    let name: String

    init(name: String) {
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate === rhs.birthDate || lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedSame
    }

    static func <(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedAscending
    }

    static func >(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedDescending
    }

}

let p1 = Person(name: "Sasha")
p1.birthDate = NSDate() 

let p2 = Person(name: "James")
p2.birthDate = NSDate()//he is older by miliseconds

if p1 == p2 {
    print("they are the same") //they are not
}

let persons = [p1, p2]

//sort the array based on who is older
let sortedPersons = persons.sorted(by: {$0 > $1})

//print sasha which is p1
print(persons.first?.name)
//print James which is the "older"
print(sortedPersons.first?.name)

You can sort array of custom objects using quick sort. Please find below example using Swift 4

func sortArrayOfPersonInAscendingOrder() {
        if self.arrSortingPersons != nil, self.arrSortingPersons.count > 0 {
            self.arrSortingPersons.sort(by: { (person1, person2) -> Bool in
                return person1.birthDate < person2.birthDate
            })
        }

        print("Sorted Array In Ascending Order:\n\(self.arrSortingPersons)")
    }

Not the answer you're looking for? Browse other questions tagged or ask your own question.