1、在该实例变量的方法缓存列表中查找方法,如果找到执行.
2、如果没找到,会去类结构中的相应方法列表中进行查找,如果找到执行.
3、如果方法列表没有找到该方法,那么就从父类中进行1、2部操作.
4、如果直到根类仍然没有找到方法,那么就会报错:unrecognized selector sent to instance 0x1005046c0.
也就是说
1、重写父类的方法,本质上不是覆盖了父类的方法,只不过是在本类中找到相应的方法,不再去父类中查找方法而已
2、super关键字并不是指父类,作用是 跳过此类直接从父类中进行查找方法
动态决议以及请求转发就是拦截上述过程,让其在runtime中运行相应的方法
//对类对象进行决议
+ (BOOL)resolveClassMethod:(SEL)sel __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
//对实例对象进行决议
+ (BOOL)resolveInstanceMethod:(SEL)sel __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
/**
* 运行时添加方法的函数
*
* @param cls 需要动态决议的类
* @param name 需要动态决议的方法
* @param imp 需要执行方法的指针(本人理解为函数指针)
* @param types 类型字符串,后面详细说
*
* @return 添加的结果
*/
(BOOL)class_addMethod(Class cls,SEL name,IMP imp,const char * types)
RunTimeTextClass1 * class1 = [[RunTimeTextClass1 alloc]init];
[class1 performSelector:@selector(Text1) withObject:@"哈哈哈哈"];
RunTime[1047:62333] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[RunTimeTextClass1 Text1]: unrecognized selector sent to instance 0x100107540'
//实例变量的动态决议,类方法的动态决议是一样的
+(BOOL)resolveInstanceMethod:(SEL)sel
{
if ([NSStringFromSelector(sel) isEqualToString:@"Text1"])
{
NSLog(@"RunTimeTextClass1 实例对象动态决议!");
class_addMethod([self class], sel, (IMP)test1, "v@:@");
}
return [super resolveInstanceMethod:sel];
}
void test1(id self,SEL _cmd,NSString *str)
{
NSLog(@"%@",str);
}
//调用不存在的方法的时候重定向到一个有该方法的对象
- (id)forwardingTargetForSelector:(SEL)aSelector __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
//将调用不存在的方法封装成NSInvocation对象传出,做完处理调用invokeWithTarget:方法触发
- (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");
RunTimeTextClass1 * class1 = [[RunTimeTextClass1 alloc]init];
[class1 performSelector:@selector(text1)];
-(id)forwardingTargetForSelector:(SEL)aSelector
{
return [[Text alloc]init];
}
//
// Text.m
// RunTime
//
// Created by YueWen on 16/2/24.
// Copyright © 2016年 YueWen. All rights reserved.
//
#import "Text.h"
@implementation Text
-(void)text1
{
NSLog(@"我是Text!");
}
@end
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
Text * text = [[Text alloc]init];
SEL selector = anInvocation.selector;
if ([text respondsToSelector:selector])//如果有这个方法
{
[anInvocation invokeWithTarget:text];//触发方法
}
else
{
[super forwardInvocation:anInvocation];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [Text instanceMethodSignatureForSelector:aSelector];
}