`-respondsToSelector:`方法的几个要点

614 阅读2分钟

-respondsToSelector:方法会查询消息的接收者所属的类是否有某消息的实现:

  • 不论是否有声明
  • 不论是它自己的, 还是它所继承的 因此, 它适用于检查一个类是否实现了其所遵守的协议所声明的optional方法.

1 -respondsToSelector:仅关心某方法是否有实现, 而不关心它是否有声明

//  MyClass.h
@interface MyClass : NSObject

- (void)aMethodWithDeclAndImpl;

- (void)aMethodWithDeclButWithoutImpl;

//- (void)aMethodWithoutDeclButWithImpl;

//- (void)aMethodWithoutDeclOrImpl;

@end
//  MyClass.m

- (void)aMethodWithDeclAndImpl {
    
}

- (void)aMethodWithoutDeclButWithImpl {   

}

@end
//  main.m
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MyClass *instanceOfMyClass = [[MyClass alloc] init];
        
        //  考察"声明的有无"和"实现的有无"对`-respondsToSelector:`返回结果的影响. 
        NSLog(@"can instance of MyClass respond to selector \"-aMethodWithDeclAndImpl\"?\t\t%@", [instanceOfMyClass respondsToSelector:@selector(aMethodWithDeclAndImpl)] ? @"YES" : @"NO");
        NSLog(@"can instance of MyClass respond to selector \"-aMethodWithDeclButWithoutImpl\"?\t\t%@", [instanceOfMyClass respondsToSelector:@selector(aMethodWithDeclButWithoutImpl)] ? @"YES" : @"NO");
        NSLog(@"can instance of MyClass respond to selector \"-aMethodWithoutDeclButWithImpl\"?\t\t%@", [instanceOfMyClass respondsToSelector:@selector(aMethodWithoutDeclButWithImpl)] ? @"YES" : @"NO");
        NSLog(@"can instance of MyClass respond to selector \"-aMethodWithoutDeclOrImpl\"?\t\t%@", [instanceOfMyClass respondsToSelector:@selector(aMethodWithoutDeclOrImpl)] ? @"YES" : @"NO");
    }

    return 0;

}

输出结果:

can instance of MyClass respond to selector "-aMethodWithDeclAndImpl"? YES

can instance of MyClass respond to selector "-aMethodWithDeclButWithoutImpl"? NO

can instance of MyClass respond to selector "-aMethodWithoutDeclButWithImpl"? YES

can instance of MyClass respond to selector "-aMethodWithoutDeclOrImpl"? NO

image.png 即, 只要有实现, 不论是否有声明, -respondsToSelector:都会返回YES.

2 -respondsToSelector:仅关心某方法是否有实现, 而不关心实现是来自于自己这个类型, 还是来自于继承

//  BaseClass.h
@interface BaseClass : NSObject

- (void)aMethodLeftUnimplemented;

- (void)aMethodImplementedByBaseClass;

- (void)aMethodImplementedByBaseClassAndOverwrittenByDerivedClass; 

@end
//  BaseClass.m
@implementation BaseClass

- (void)aMethodImplementedByBaseClass {
    
}

- (void)aMethodImplementedByBaseClassAndOverwrittenByDerivedClass {
    
}

@end

//  DerivedClass.h
@interface DerivedClass : BaseClass

- (void)aMethodImplementedByDerivedClass; 

@end
//  DerivedClass.m
@implementation DerivedClass

- (void)aMethodImplementedByBaseClassAndOverwrittenByDerivedClass {
    
}

- (void)aMethodImplementedByDerivedClass {
    
}

@end
//  main.m
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        DerivedClass *instanceOfDerivedClass = [[DerivedClass alloc] init];

        NSLog(@"can instance of DerivedClass respond to selector \"-aMethodLeftUnimplemented\"?\t\t%@", [instanceOfDerivedClass respondsToSelector:@selector(aMethodLeftUnimplemented)] ? @"YES" : @"NO");
        NSLog(@"can instance of DerivedClass respond to selector \"-aMethodImplementedByBaseClass\"?\t\t%@", [instanceOfDerivedClass respondsToSelector:@selector(aMethodImplementedByBaseClass)] ? @"YES" : @"NO");
        NSLog(@"can instance of DerivedClass respond to selector \"-aMethodImplementedByBaseClassAndOverwrittenByDerivedClass\"?\t\t%@", [instanceOfDerivedClass respondsToSelector:@selector(aMethodImplementedByBaseClassAndOverwrittenByDerivedClass)] ? @"YES" : @"NO");
        NSLog(@"can instance of DerivedClass respond to selector \"-aMethodImplementedByDerivedClass\"?\t\t%@", [instanceOfDerivedClass respondsToSelector:@selector(aMethodImplementedByDerivedClass)] ? @"YES" : @"NO");
    }
    return 0;
}

输出结果:

can instance of DerivedClass respond to selector "-aMethodLeftUnimplemented"? NO

can instance of DerivedClass respond to selector "-aMethodImplementedByBaseClass"? YES

can instance of DerivedClass respond to selector "-aMethodImplementedByBaseClassAndOverwrittenByDerivedClass"? YES

can instance of DerivedClass respond to selector "-aMethodImplementedByDerivedClass"? YES

image.png 即, 只要有实现, 不论是自己的实现还是继承得来的实现, -respondsToSelector:都会返回YES.

3 根据这两条可知, 这个方法应当配合协议使用, 用以验证是否实现了协议要求的optional方法(做introspection).