'Sorting objects in NSMutableArray with sortUsingComparator
I have the following mutable array:
NSMutableArray *persons = [[NSMutableArray alloc]initWithObjects:person1, person2, person3, nil];
where every person is an object, which contains (NSInteger) personAge and (NSString*) personName properties. Now I want to sort this array by personAge. So I tried the following:
[persons sortUsingComparator:
     ^NSComparisonResult(id obj1, id obj2)
     {
         Person *p1 = (Person*)obj1;
         Person *p2 = (Person*)obj2;
        return [p1.personAge compare: p2.personAge];
     }];
    NSLog(@"%ld", [persons componentsJoinedByString:@" "]);
But I'm getting a "Bad receiver type 'NSInteger' (aka 'long')" error message in the return line. Also I have a warning in the NSLog line: "Format specifies type 'long' but the argument has type 'NSString *'". How do I fix it?
Solution 1:[1]
Shouldn't you use something like this instead?
[persons sortUsingComparator:
    ^NSComparisonResult(id obj1, id obj2) {
        Person *p1 = (Person*)obj1;
        Person *p2 = (Person*)obj2;
        if (p1.personAge > p2.personAge) {
            return (NSComparisonResult)NSOrderedDescending;
        }
        if (p1.personAge < p2.personAge) {
            return (NSComparisonResult)NSOrderedAscending;
        }
        return (NSComparisonResult)NSOrderedSame;
    }
];
The thing is that you have rely on the compare method which doesn't exist on NSInteger: it is only a typedef of int. So you want to compare integer value instead and returns an NSComparisonResult value to denote the ordering of your object accordingly.
Solution 2:[2]
You're trying to call compare: on an NSInteger, which is not an object; it's a typedef for an integer type (either int or long depending on architecture).
Also, componentsJoinedByString: returns an NSString, not an integer.
Try:
[persons sortUsingComparator:
    ^NSComparisonResult(id obj1, id obj2)
    {
        Person *p1 = (Person*)obj1;
        Person *p2 = (Person*)obj2;
        if (p1.personAge < p2.personAge)
            return NSOrderedAscending;
        if (p1.personAge > p2.personAge)
            return NSOrderedDescending;
        return NSOrderedSame;
 }];
NSLog(@"%@", [persons componentsJoinedByString:@" "]);
Solution 3:[3]
Regarding the "Bad receiver type..." error, NSInteger is a primitive data type (not an Objective-C class) so you can't call methods on it. what you want to do is the following:
if (p1.personAge > p2.personAge) {
    return (NSComparisonResult)NSOrderedDescending;
}
if (p1.personAge < p2.personAge) {
    return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
The warning is due to the fact that @"%ld" is the format string for a long (as the warning says), but -componentsSeparatedByString: returns an NSString object. The correct format string for any Objective-C object is @"%@", so the line should read NSLog(@"%@", [persons componentsJoinedByString:@" "]);.
Solution 4:[4]
Like tigeguero's answer but tidier:
 [people sortUsingComparator:
      ^NSComparisonResult(Person* p1, Person* p2){
            if (p1.personAge > p2.personAge) {
                return NSOrderedDescending;
            }
            else if (p1.personAge < p2.personAge) {
                return NSOrderedAscending;
            }
            else{
                return NSOrderedSame;
            } 
    }
 ];
Solution 5:[5]
[YOURMutableArray sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Iulian Onofrei | 
| Solution 2 | Wevah | 
| Solution 3 | jrtc27 | 
| Solution 4 | malhal | 
| Solution 5 | Hiren | 
