tags:

views:

104

answers:

3

I would like to know if an instance implements a specific method. I could use respondsToSelector: but it returns YES if the instance inherits the method...

I could loop through the methods of class_copyMethodList(), but since I might want to check a lot of instances, I wanted to know if there was a simpler solution (like repondsToSelector:, but restricted to the class itself...)

edit: since I really think there is no function or method doing that, I wrote mine. Thanks for your answers, here is the method if it can be of any use :

+ (BOOL)class:(Class)aClass implementsSelector:(SEL)aSelector
{
    Method          *methods;
    unsigned int    count;
    unsigned int    i;

    methods = class_copyMethodList(aClass, &count);
    BOOL implementsSelector = NO;
    for (i = 0; i < count; i++) {
        if (sel_isEqual(method_getName(methods[i]), aSelector)) {
            implementsSelector = YES;
            break;
        }
    }
    free(methods);
    return implementsSelector;
}
+1  A: 

You can use reflection to do that.

Pablo Santa Cruz
+1 I can't think of another way to do it that restricts it to just a single class and not any of the superclasses
Dave DeLong
Yep, I figured, but the only appropriate function in the list seems to be class_respondsToSelector() and the discussion part advises me to use either respondsToSelector: or instancesRespondToSelector: which both returns YES if the method is inheritedSo with reflection the only solution would be to use class_copyMethodList() ? Or I didn't read well enough the documentation ?
Thomas Joulin
A: 

It's probably easier to check whether the method your own class returns is the same or different than the method your superclass returns.

if ([[obj class] instanceMethodForSelector:sel] != [[obj superclass] instanceMethodForSelector:sel]) {
    NSLog(@"%@ directly implements %@", [obj class], NSStringFromSelector(sel));  
}
Ken
A: 

instance responds and super does not:

-(BOOL) declaresSelector:(SEL)inSelector {
  return [self respondsToSelector:inSelector] && ![super respondsToSelector:inSelector];
}

instance responds and is different than super:

-(BOOL) implementsSelector:(SEL)inSelector {
  return [self respondsToSelector:inSelector] && !( [super respondsToSelector:inSelector] && [self methodForSelector:inSelector] == [super methodForSelector:inSelector] );
}

According to Apple documents you should call respondsToSelector before methodForSelector.

drawnonward