14

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?

5 Answers 5

39

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.

Sign up to request clarification or add additional context in comments.

13 Comments

Yep, same result as in the above answer: <Person: 0x10010a720> <Person: 0x10010ad20> <Person: 0x100108ab0> And the same question: Is there any way that instead of Person: xxxxxxx I would get the actual personAge? So it would look something like that: 1, 27, 34 etc..?
[p1.personAge intValue] I think you are printing your NSNumber object
OK, I'm confused now... Did you mean I should do something like that: if ([p1.personAge intValue] > [p2.personAge intValue]) { return (NSComparisonResult)NSOrderedDescending; }? Then I'm still getting the "Bad receiver..." error. Still have no idea how to print the age of each person...
Sorry if i wasn't clear you just need to do a NSLog with the right format: NSLog(@"Age: %d", p1.personAge)
forget about my comment with the NSNumber object, you are using NSInteger, it is a typedef of an integer
|
4

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:@" "]);

3 Comments

I tried it and I got this result: <Person: 0x10010a720> <Person: 0x10010ad20> <Person: 0x100108ab0> Is there any way that instead of Person: xxxxxxx I would get the actual personAge? So it would look something like that: 1, 27, 34 etc..?
[[persons valueForKey:@"personAge"] componentsJoinedByString:@" "]
@Igal, you could also write a description method in your Person class, so that when you do NSLog(@"%@",aPerson), you get something like: "name:Bill, age:26" instead of <Person: 0x10010a720>.
1

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:@" "]);.

2 Comments

Is there any way that I could get the actual personAge? So it would look something like that: 1, 27, 34 etc.. instead of Person: xxxxxxx in the result?
Easiest way is to override the -description method in your Person class to return what you want it to display as.
0

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;
            } 
    }
 ];

Comments

0
[YOURMutableArray sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

1 Comment

While this may in fact answer the question, can you elaborate on what this code actually does?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.