Search code examples
objective-cmismatch

Multiple methods named 'setYear' found with mismatch result


I'm a beginner of Objective C, trying to write a simple program print the birth year of a person, but there is an error "Multiple methods named 'setYear' found with mismatch result", can anyone help me figure out why it happens?

//person.h
@interface person : NSObject
@property int year;
+ (id)person;
@property (readonly) NSString* summary;
@end

//  main.m
#import "person.h"
@implementation person
@synthesize year;
+ (id)book{
    person *somePerson = [[self alloc] init];
    return somePerson;
}

- (NSString*)summary{
    NSNumber* yearAsObject;
    yearAsObject = [NSNumber numberWithInteger:self.year];
    return [NSString stringWithFormat:@"Borned in %@.", yearAsObject];
}
@end

int main(){
    @autoreleasepool {
        id aperson = [person person];
        [aperson setYear:@1970];
        NSLog (@"Birth year: %@", [aperson summary]);
    }
return 0;

}


Solution

  • It's a bad idea to use the id type on variables if you know which type you're going to put there. That's because by using id instead of the real class name, the compiler simply doesn't know what kind of sanity checks to perform.

    In this particular case, the compiler sees the method setYear: but since it doesn't know it should be a person object (please stick to Objective-C naming conventions and rename the class to Person instead), it looks up all methods called setYear: it can find. It'll find your property of type int, but it will also find -[NSDateComponents setYear:] which expects a NSInteger, which is either an int or long. If you're building for 64-bit, it'll be a long.

    So now the compiler knows there exist two methods setYear:, one expects an int, the other a long. The compiler does not know which one you mean since the type of aperson is id.

    There are two solutions: either put a cast in the call as in [(person *)aperson setYear:1970] (passing @1970, which is a NSNumber, is wrong here). The better solution is to actually tell the compiler your intention and specify the correct type of the variable:

    person *aperson = [person person];
    [person setYear:1970];