1 动态添加方法的使用场景
对于APP,当某些功能并不是每个人都可以使用时,比如微博会员机制、某些付费才有的功能,这些方法可以采取动态添加的方式实现.
2 为什么需要动态添加方法?
OC都是懒加载,如果在类中实现方法,在类加载内存的时候,就会把方法加载好,放在类的方法列表中,占用内存空间。某些方法,对于某些人来说可能一辈子都不会使用,就没有必要添加到内存中。
3 performSelector方法之简介
- performSelector方法是iOS中的一种方法调用方式。他可以向一个对象传递任何消息,而不需要在编译的时候声明这些方法。所以这也是runtime的一种应用方式。
- performSelector和直接调用方法的区别:
- (1)直接调用方法编译时会自动校验,如果方法不存在,在编译时候就能够发现,编译器会直接报错。
- (2)使用performSelector的话一定是在运行时候才能发现,如果方法不存在,编译时不会报错,但在运行时一定会崩溃。
- (3)如果使用performSelector的话,他有个最佳伴侣- (BOOL)respondsToSelector:(SEL)aSelector;来判断在运行时对象是否响应此方法。
4 动态添加方法的使用举例
- 添加没有参数的方法
// 1.创建Person 对象
Person *p = [[Person alloc] init];
// 2.调用没有实现的eat方法
[p performSelector:@selector(eat)];
// 3.在person.m文件中调用方法:
// 作用:调用了一个未实现方法时一定会来到这里
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// 判断方法名是不是eat
if (sel == NSSelectorFromString(@"eat")) {
// 动态添加eat方法
/*
第一个参数:给哪个类添加方法
第二个参数:添加什么方法
第三个参数IMP:方法实现,函数入口:函数名
第四个参数:方法类型
v 没有返回值
@ 对象 id
: 方法
*/
class_addMethod(self, @selector(eat), eat, "v@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
// 4.eat方法实现
// self:方法调用者
// _cmd:当前方法编号
// 任何一个方法都能调用self,_cmd,其实任何一个方法都有这两个隐式参数
void eat(id self, SEL _cmd)
{
NSLog(@"吃东西");
}
- 添加有参数的方法
// 2.调用没有实现的run方法
[p performSelector:@selector(run:) withObject:@10];
// 3.在person.m文件中调用方法:
// 作用:调用了一个未实现方法时一定会来到这里
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// 判断方法名是不是eat
if (sel == NSSelectorFromString(@"run:")) {
// 动态添加run方法
/*
第一个参数:给哪个类添加方法
第二个参数:添加什么方法
第三个参数IMP:方法实现,函数入口:函数名
第四个参数:方法类型
v 没有返回值
@ 对象 id
: 方法
*/
class_addMethod(self, @selector(run:), run, "v@:@");
return YES;
}
return [super resolveInstanceMethod:sel];
}
// 4.run方法实现
// self:方法调用者
// _cmd:当前方法编号
// 任何一个方法都能调用self,_cmd,其实任何一个方法都有这两个隐式参数
void run(id self, SEL _cmd, NSNumber *metre)
{
NSLog(@"跑了%@米",metre);
}