Jim
Jim

Reputation: 226

Why am I getting "unrecognized selector" errors?

I'm trying to teach myself objective-c. I used to (~10yr's ago) be pretty good with c++ so I figured this shouldn't be too hard, but after so many years of python and various mathematical programming languages I'm pretty rusty on pointers and such, which I assume is probably what's causing this.

Anyway, I keep getting unrecognized selector errors for methods that definitely exist in the documentation and xcode's debugging output (which I'm not super familiar with so maybe this is wrong) shows that these objects are initialized. I've tried to make the following example as small as I can. Here is a class I've written:

// Graph.h

#import <Foundation/Foundation.h>

@interface Graph : NSObject

@property NSMutableSet *myObjects;
- (id)initWithNumElements:(int)total;
- (NSMutableSet *)addOneMore:(NSMutableSet *)vertices;
- (NSMutableSet *)addTo:(NSMutableSet *)R from:(NSMutableSet *)P;

@end

and it's implementation:

// Graph.m

#import "Graph.h"

@implementation Graph

// Put numbers 0, ..., total - 1 into the objects of self
- (id)initWithNumElements:(int)total {
    self = [super init];
    if (self) {
        NSMutableSet *objects = [[NSMutableSet alloc] init];
        for (int i=0; i<total; i++) {
            [objects addObject:[NSNumber numberWithInt:i]];
        }
        _myObjects = objects;
    }
    return self;
}

// If possible, add one of the objects of self to set
- (NSMutableSet *)addOneMore:(NSMutableSet *)set {
    NSMutableSet *allObjects = [self.myObjects copy];
    for (id elt in set) {
        [allObjects removeObject:elt];
    }
    //[allObjects minusSet:set];
    return [self addTo:[set copy] from:allObjects];
}

// If possible, add one object from P to R
- (NSMutableSet *)addTo:(NSMutableSet *)R from:(NSMutableSet *)P {
    if ([P count] == 0) {
        return R;
    }
    id v = [P anyObject];
    [R addObject:v];
    return R;
}

@end

and I'm testing it with the following code:

// main.m

#import <Foundation/Foundation.h>
#import "Graph.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Graph *G = [[Graph alloc] initWithNumElements:6];
        NSMutableSet *results = [G addOneMore:[[NSMutableSet alloc] init]];
        NSLog(@"%@", results);
    }
    return 0;
}

(I know logically this code doesn't make any sense. It's simplified to stupidity from something that once made only a small amount of sense.)

I get the error

2014-10-27 11:19:14.936 Test[1469:303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSetI addObject:]: unrecognized selector sent to instance 0x100108a20'

and xcode points me exactly to the line "[R addObject:v];". But the debug stuff says that R is an NSMutableSet* and v is an _NFCSNumber* so what's the problem? That should be valid as far as I can tell.

The commented out line "//[allObjects minusSet:set];" was also generating an unrecognized selector error which does not occur when I replace it with the for loop that's above it. Again that line should be valid as far as I can see, I can't figure out what's wrong here.

Upvotes: 0

Views: 487

Answers (1)

Steve Madsen
Steve Madsen

Reputation: 13791

In addOneMore:, the line

NSMutableSet *allObjects = [self.myObjects copy];

does not assign a mutable set to allObjects, but rather an immutable NSSet. If you want a mutable copy, you need to use mutableCopy, even when the source container (set, array, dictionary) is a mutable variant. copy returns immutable instances.

You're getting an unrecognized selector error because addObject: isn't a valid selector for an immutable set.

Upvotes: 7

Related Questions