Ramy Al Zuhouri
Ramy Al Zuhouri

Reputation: 21986

Sorting a NSMutableArray of strings: 'unrecognized selector sent to instance'

I have made a program that gets some strings in input from the user (it stops typing "exit"), puts them in a NSMutableArray and sort them:

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>

NSInteger compare( id id1, id id2, void* context)
{
    NSString* str1=[id1 stringValue], *str2=[id2 stringValue]; /* ****** exception here */
    const char* buf1, *buf2;
    buf1=[str1 UTF8String];
    buf2=[str2 UTF8String];
    if(strcmp(buf1,buf2)<0)
        return NSOrderedAscending;
    else
        return NSOrderedDescending;
}


int main (int argc, const char * argv[])
{
    NSAutoreleasePool* pool=[[NSAutoreleasePool alloc]init];
    NSMutableArray* array=[[NSMutableArray alloc]init];
    NSString* str=@"";
    char buffer[100];
    NSLog(@"Type a sequence of strings, ending with 'exit', the strings will be sorted in alphabethical order");
    while(! [str isEqualToString:@"exit\n"])
    {
        fgets(buffer,100,stdin);
        str=[NSString stringWithUTF8String: buffer];
        [array addObject: str];

    }
    [array sortUsingFunction: compare context: NULL];
    [array release];
    [pool drain];
    return 0;
}

But I get an exception in the line that I have marked with "**", it says:

2012-05-09 00:10:14.502 CLITest[1029:903] -[NSCFString stringValue]: unrecognized selector sent to instance 0x10010cbf0

It seems like it doesn't take the string value from the id.Why? How should I change the comparator method?

Upvotes: 0

Views: 322

Answers (1)

Manlio
Manlio

Reputation: 10864

id1 and id2 are actually NSStrings, even if they are casted to id and passed to your function (this approach is useful because you can define your compare function in order to sort custom objects).

It doesn't make sense to call stringValue on a string (and, in fact, NSString do not have a member function named stringValue).

To work with strings just cast back to NSStrings.

NSString *s1 = (NSString*) id1;
NSString *s2 = (NSString*) id2;

This is not strictly necessary (you can even work directly with id1 and id2) but casting will avoid you to get compiler warnings (also it's a clearer code).

Upvotes: 4

Related Questions