ios开发runtime学习三:动态添加方法(实际应用少,面试)
#import "ViewController.h" #import "Person.h" /* 1: Runtime(动态添加方法):OC都是懒加载机制,只要一个方法实现了,就会马上添加到方法列表中. app:免费版,收费版 QQ,微博,直播等等应用,都有会员机制 performSelector:去执行某个方法。performSelector withObject :object为前面方法的参数 2: 美团有个面试题?有没有使用过performSelector,什么时候使用?动态添加方法的时候使用过?怎么动态添加方法?用runtime?为什么要动态添加方法? */ @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // _cmd:当前方法的方法编号 Person *p = [[Person alloc] init]; // 执行某个方法 // [p performSelector:@selector(eat)]; [p performSelector:@selector(run:) withObject:@10]; } @end
#import "Person.h" #import <objc/message.h> @implementation Person // 没有返回值,也没有参数 // void,(id,SEL) void aaa(id self, SEL _cmd, NSNumber *meter) { NSLog(@"跑了%@", meter); } // 任何方法默认都有两个隐式参数,self,_cmd(_cmd代表方法编号,打印结果为当前执行的方法名) // 什么时候调用:只要一个对象调用了一个未实现的方法就会调用这个方法,进行处理 // 作用:动态添加方法,处理未实现 + (BOOL)resolveInstanceMethod:(SEL)sel { // [NSStringFromSelector(sel) isEqualToString:@"eat"]; if (sel == NSSelectorFromString(@"run:")) { // eat // class: 给哪个类添加方法 // SEL: 添加哪个方法 // IMP: 方法实现 => 函数 => 函数入口 => 函数名 // type: 方法类型:void用v来表示,id参数用@来表示,SEL用:来表示 //aaa不会生成方法列表 class_addMethod(self, sel, (IMP)aaa, "v@:@"); return YES; } return [super resolveInstanceMethod:sel]; } //- (void)test //{ // // [NSStringFromSelector(sel) isEqualToString:@"eat"]; // if (sel == NSSelectorFromString(@"eat")) { // // eat // // class: 给哪个类添加方法 // // SEL: 添加哪个方法 // // IMP: 方法实现 => 函数 => 函数入口 => 函数名 // // type: 方法类型 // class_addMethod(self, sel, (IMP)aaa, "v@:"); // // return YES; // } // // return [super resolveInstanceMethod:sel]; //} @end
####3.动态添加方法
* 开发使用场景:如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。
* 经典面试题:有没有使用performSelector,其实主要想问你有没有动态添加过方法。
* 简单使用
```
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Person *p = [[Person alloc] init];
// 默认person,没有实现eat方法,可以通过performSelector调用,但是会报错。
// 动态添加方法就不会报错
[p performSelector:@selector(eat)];
}
@end
@implementation Person
// void(*)()
// 默认方法都有两个隐式参数,
void eat(id self,SEL sel)
{
NSLog(@"%@ %@",self,NSStringFromSelector(sel));
}
// 当一个对象调用未实现的方法,会调用这个方法处理,并且会把对应的方法列表传过来.
// 刚好可以用来判断,未实现的方法是不是我们想要动态添加的方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
if (sel == @selector(eat)) {
// 动态添加eat方法
// 第一个参数:给哪个类添加方法
// 第二个参数:添加方法的方法编号
// 第三个参数:添加方法的函数实现(函数地址)
// 第四个参数:函数的类型,(返回值+参数类型) v:void @:对象->self :表示SEL->_cmd
class_addMethod(self, @selector(eat), eat, "v@:");
}
return [super resolveInstanceMethod:sel];
}
@end
```
posted on 2016-09-14 13:04 Hello_IOS 阅读(3313) 评论(0) 编辑 收藏 举报