补充:respondsToSelector
+(BOOL)respondsToSelector:(SEL)aSelector
这个函数大家再熟悉不过了,用来检查对象是否实现了某函数。
此函数通常是不需要重载的,但是在动态实现了查找过程后,需要重载此函数让对外接口查找动态实现函数的时候返回YES,保证对外接口的行为统一。
- (BOOL) respondsToSelector:(SEL)aSelector
{
if (@selector(setTitle:) == aSelector ||
@selector(title) == aSelector ||
@selector(setAuthor:) == aSelector ||
@selector(author) == aSelector)
{
return YES;
}
return [super respondsToSelector: aSelector];
}
//全局函数
1.void dynamicMethodIMP(id self, SEL _cmd)
{
// implementation ....
}
2.+ (BOOL) resolveInstanceMethod:(SEL)aSEL
{
if (aSEL == @selector(resolveThisMethodDynamically))
{
class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:aSel];
}
//将消息转出某对象
3.- (id)forwardingTargetForSelector:(SEL)aSelector
{
NSLog(@"MyTestObject _cmd: %@", NSStringFromSelector(_cmd));
NoneClass *none = [[NoneClass alloc] init];
if ([none respondsToSelector: aSelector]) {
return none;
}
return [super forwardingTargetForSelector: aSelector];
}
4.- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
NSString *sel = NSStringFromSelector(selector);
if ([sel rangeOfString:@"set"].location == 0) {
//动态造一个 setter函数
return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
} else {
//动态造一个 getter函数
return [NSMethodSignature signatureWithObjCTypes:"@@:"];
}
}
5.- (void)forwardInvocation:(NSInvocation *)invocation
{
//拿到函数名
NSString *key = NSStringFromSelector([invocation selector]);
if ([key rangeOfString:@"set"].location == 0) {
//setter函数形如 setXXX: 拆掉 set和冒号
key = [[key substringWithRange:NSMakeRange(3, [key length]-4)] lowercaseString];
NSString *obj;
//从参数列表中找到值
[invocation getArgument:&obj atIndex:2];
[data setObject:obj forKey:key];
} else {
//getter函数就相对简单了,直接把函数名做 key就好了。
NSString *obj = [data objectForKey:key];
[invocation setReturnValue:&obj];
}
}