10

I can't piece together how to do this.

I fetch my array from a plist, this array is full of numbers (as set in the plist). Now al I need to do is sort them so they are descending, but I can't work it out.

halfer
  • 19,824
  • 17
  • 99
  • 186
Josh Kahane
  • 16,765
  • 45
  • 140
  • 253

5 Answers5

43

Try this code?

 NSArray *array = /* loaded from file */;
 array = [array sortedArrayUsingSelector: @selector(compare:)];
Alexsander Akers
  • 15,967
  • 12
  • 58
  • 83
  • But what would the contents of the selector method be? This is what gets me. – Josh Kahane Jun 24 '12 at 16:57
  • 2
    The `-compare:` method is defined for `NSNumber` instances: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/Reference/Reference.html#//apple_ref/occ/instm/NSNumber/compare: – Alexsander Akers Jun 24 '12 at 16:59
  • Thats the one I meant. Perhaps I misunderstanding the docs, but I have tried with and without the compare method and it always crashing the app saying unrecognised selector. – Josh Kahane Jun 24 '12 at 17:07
  • That's weird. Something must be up with your array then. – Alexsander Akers Jun 24 '12 at 17:09
  • Hmm, its literally an arrays which looks like this: 1, 54, 23, 11, 8, 67. I'll look further into it. – Josh Kahane Jun 24 '12 at 17:10
  • 1
    It seems that (from your comment on the other answer) that you've populated your .plist with numbers *as strings* and not *as numbers*. – Alexsander Akers Jun 24 '12 at 17:10
  • Am I the only one who finds this stupidly complicated? There's seriously no method for `NSArray` called `sortedArray` which calls exactly this? I love extensions and all, but why do I (and everyone else) have to write such basic stuff that Apple should have had in the standard libraries all along? Although Obj-C is a flawed language and Swift can't come quickly enough, it seems to me a bigger problem is the lousy libraries. I hope Swift's libraries don't leave me having to write out this basic stuff myself. – ArtOfWarfare Jul 09 '14 at 01:32
  • @ArtOfWarfare: Since Arrays can hold any type of object, including entire subarrays and dictionaries, it's impossible to have a generic sorting routine that automatically knows how to sort your objects. Let's say you have an array of UIViewControllers. How should they be sorted? – Owen Hartnett Aug 09 '16 at 12:17
  • @OwenHartnett - It should always use `compare:`. If the class you've inserted into your `NSArray` doesn't implement that method, then you shouldn't be using the `sortedArray` method. You'll have to fall back to the more flexible `sortedArrayUsingSelector:` method. – ArtOfWarfare Aug 09 '16 at 13:25
  • You can't always use compare: . In objective C, arrays can hold mixed types: You might have a string, and NSNumber, a UIViewController and a NSDate all in the same array, yet there may be logical reason where a sort is appropriate. Having a generic compare: as a default method could generate unattainable expectations and be very difficult to debug without checking the types of the array items. – Owen Hartnett Aug 09 '16 at 18:10
16

The following will sort the numbers in ascending order and then reverse the result to give the numbers in descending order:

NSArray *sorted = [[[array sortedArrayUsingSelector:@selector(compare:)] reverseObjectEnumerator] allObjects];

This previous question has some other alternatives: Sort an NSArray in Descending Order

Community
  • 1
  • 1
mttrb
  • 8,297
  • 3
  • 35
  • 57
  • Im getting a crash with `-[__NSCFString sortedArrayUsingSelector:]: unrecognized selector sent to instance`. – Josh Kahane Jun 24 '12 at 17:09
  • Are you sure you calling `sortedArrayUsingSelector:` on an `NSArray`? You appear to be calling `sortedArrayUsingSelector:` on an `NSString`. You should probably check the data structure that is being loaded from the Plist. – mttrb Jun 24 '12 at 17:11
  • @Josh Kahane, if so, you are most likely having issues with memory management, because your `array` pointer points to `NSString` object. Forgot to retain / too much [auto]releases? – ivanzoid Jun 24 '12 at 17:13
  • This answer fully answer's the question, as it sorts the array *descending*. – adamjansch Nov 11 '19 at 10:35
13

Here is one of many methods using comparison block. This code snippet is handy for any array with numbers that you want to sort. For Ascending order:

AscendingArray = [UnsortArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    if ([obj1 integerValue] > [obj2 integerValue]) {
      return (NSComparisonResult)NSOrderedDescending;
    }

    if ([obj1 integerValue] < [obj2 integerValue]) {
      return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
  }];

For Descending order:

DescendingArray = [UnsortArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    if ([obj1 integerValue] > [obj2 integerValue]) {
      return (NSComparisonResult)NSOrderedAscending;
    }

    if ([obj1 integerValue] < [obj2 integerValue]) {
      return (NSComparisonResult)NSOrderedDescending;
    }
    return (NSComparisonResult)NSOrderedSame;
  }];
Ohmy
  • 2,201
  • 21
  • 24
  • 1
    why not just use NSNumber `compare:`? – vikingosegundo Mar 04 '15 at 17:57
  • I've used this method because even if some of my data are numbers, I've stored everything as string. This method can compare numbers that are stored as strings, contrary to compare: method – AnthoPak Mar 21 '18 at 09:06
5

It work for me:

NSSortDescriptor *sortIdClient = 
[NSSortDescriptor sortDescriptorWithKey:@"campaignValue"
                              ascending:NO
                             comparator: ^(id obj1, id obj2){

    return [obj1 compare:obj2 options:NSNumericSearch];

 }];

NSArray *sortDescriptors = @[sortIdClient];

NSArray *arrTemp = [self.allCampaignsList sortedArrayUsingDescriptors:sortDescriptors];
Alex Cio
  • 6,014
  • 5
  • 44
  • 74
Duyen Hang Kim
  • 173
  • 2
  • 7
0

This Will solve the problem:

 NSArray *array = /* loaded from file */;
 array = [array sortedArrayUsingSelector: @selector(compare:)];
Gustavo Morales
  • 2,614
  • 9
  • 29
  • 37
Jasim
  • 60
  • 1