有没有使用过performSelector,
使用过
什么时候使用?
动态添加方法的时候使用过
怎么动态添加方法?
使用runtime
为什么要动态添加方法?
OC都是懒加载机制,只要一个方法实现了,就会马上添加到方法列表上.方法中有很多映射关系,这无形中就会消耗了内存
比如一个app:有免费版、收费版
比如:QQ、微博、直播等等应用,都有会员机制,这样我们可以动态添加方法1
Runtime (动态添加方法):
如果我们创建一个Person类,然后在viewDidLoad中创建该对象,我们使用performSelector去调用一个Person类中没有的方法,结果系统报错找不到方法:
-
Person *p = [[Person alloc]init]; // 执行某个方法 [p performSelector:@selector(eat)];
-
#import <Foundation/Foundation.h> @interface Person : NSObject @end #import "Person.h" #import <objc/message.h> @implementation Person @end
这时候我们可以动态去添加方法:
- 首先:我们在Person 类中去实现一个方法:
-
// 任何方法默认都有两个隐式参数,self,_cmd // 作用:动态添加方法、或者处理一些未实现的方法 // 什么时候调用?只要一个对象调用了一个未实现的方法,就会调用这个方法来进行处理 + (BOOL)resolveInstanceMethod:(SEL)sel { //NSLog(@"%@",NSStringFromSelector(sel)); //[NSStringFromSelector(sel) isEqualToString:@"eat"] if (sel == NSSelectorFromString(@"eat")) { // class:第一个参数:给那个类添加方法 // SEL:添加哪个方法 // IMP:implementation:方法=>函数=>函数的入口=>函数名 // type:方法的类型 class_addMethod(self, sel, (IMP)funcA, "v@:"); return YES; } return [super resolveInstanceMethod:sel]; }
2.主要是这个方法的参数我们要掌握:class_addMethod(self, sel, (IMP)funcA, "v@:");
查看参数文档地址:xcode-->window-->Documentation and API Reference-->展开ios9.3-->Languages & Utilities-->Objective-C-->Guides-->Objective-C Runtime Programming Guide-->Dynamic Method Resolution + Type Encodings
Runtime中文文档地址链接: http://blog.youkuaiyun.com/liangliang103377/article/details/39007683
-
// 声明一个函数 void funcA(id self,SEL _cmd) { NSLog(@"吃东西"); }
- 最后打印:吃东西
如果我们是动态创建一个带有参数的方法:
-
#import "Person.h" #import <objc/message.h> @implementation Person // 声明一个函数 void funcA(id self,SEL _cmd,NSNumber *metre) { NSLog(@"跑了%@米",metre); } + (BOOL)resolveInstanceMethod:(SEL)sel { //NSLog(@"%@",NSStringFromSelector(sel)); //[NSStringFromSelector(sel) isEqualToString:@"eat"] if (sel == NSSelectorFromString(@"run:")) { // class:第一个参数:给那个类添加方法 // SEL:添加哪个方法 // IMP:implementation:方法=>函数=>函数的入口=>函数名 // type:方法的类型 class_addMethod(self, sel, (IMP)funcA, "v@:@"); return YES; } return [super resolveInstanceMethod:sel]; } @end
方法的调用:
-
- (void)viewDidLoad { [super viewDidLoad]; // _cmd:当前方法方法编号 NSLog(@"%@",NSStringFromSelector(_cmd)); Person *p = [[Person alloc]init]; // 执行某个方法 [p performSelector:@selector(run:) withObject:@100]; }
最后打印:跑了100米
知识点:
- 1:任何方法默认都有两个隐式参数:self、_cmd
- 2:_cmd:当前方法方法编号
- 在ViewDidLoad中打印该参数:
- NSLog(@"%@",NSStringFromSelector(_cmd));
3:+ (BOOL)resolveInstanceMethod:(SEL)sel ?作用?什么时候调用?
>什么时候调用?只要一个对象调用了一个未实现的方法,就会调用这个方法来进行处理
>作用?动态添加方法、或者处理一些未实现的方法
意见反馈邮件:1415429879@qq.com
欢迎你们的阅读和赞赏、谢谢!