03 runtime用法之动态添加方法

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);
}

你可能感兴趣的:(03 runtime用法之动态添加方法)