'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 |