'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