程序员iOS学习开发iOS进阶指南

runtime - 动态添加方法

2016-06-08  本文已影响316人  我的梦想之路

动态添加方法:
动态添加就运用到懒加载
开发场景:如果一个类方法很多,加载类到内存的时候也比较耗费资源,需要给每个方法生成一个映射表(这个词我也不懂),可以使用动态给某个类添加方法。

 Person *p = [[Person alloc]init];
 //performSelector:即为动态添加方法
 [p performSelector:@selector(eat) withObject:nil];
// 会报警告,运行后会报错,报的错误是因为你没有在Person类里面实现eat方法

如果你想自己动态添加方法
首先你要在类中实现代码如下:

#首先介绍相关的方法,后面再整合
/**
处理实例方法
 动态添加方法,首先实现这个resolveInstanceMethod方法
 resolveInstanceMethod调用的情况:当调用了一个没有实现的方法,就会调用resolveInstanceMethod这个方法
 <#sel#>:没有实现的方法
 */
+ (BOOL)resolveInstanceMethod:(SEL)sel{}

// runtime 方法(导入<objc/message.h>)
class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>)

         <#__unsafe_unretained Class cls#>:表示给哪个类添加  -- self 
         <#SEL name#>:方法编号 即为 方法名 -- 未实现的方法
         <#IMP imp#> :方法的实现,函数入口,函数指针或函数名 --在本类的@implementation 类名 下面
    // 定义一个函数(函数名随便写,IMP要与之一致)
   void tangtang_eat(){
    
    }

         <#const char *types#> :方法的类型 ---查看xcode help document文档
 xcode --> help --> document -->搜索runtime --> 方法class_addMethod --> 查看<#const char *types#>用法(也有整个动态添加方法的描述)

#根据苹果系统的东西来
#import "Person.h"

#import <objc/message.h>

@implementation Person

/**
 默认一个方法都有两个参数,self,_cmd,为隐式参数,不显示
 self :方法的调用者
 _cmd :调用方法的编号,即方法名
 */
//1. 定义一个函数(函数名随便写)
// 无返回值,参数(id,SEL)
void tangtang_eat(id self, SEL _cmd){
    
    NSLog(@"调用糖糖的eat方法 %@ %@",self,NSStringFromSelector(_cmd));
}



/**
 2.处理为实现的实例方法
 动态添加方法,首先实现这个resolveInstanceMethod方法
 resolveInstanceMethod调用的情况:当调用了一个没有实现的方法,就会调用resolveInstanceMethod这个方法
 <#sel#>:没有实现的方法
 */
+ (BOOL)resolveInstanceMethod:(SEL)sel{
    
    // 动态添加未实现的方法
    if (sel == @selector(eat)) {
        /**
         v : void
         @ : 对象
         : : SEL
         */
        class_addMethod(self, sel, (IMP)tangtang_eat, "v@:");
       
        // 处理完
        return YES;
    }
    
    
    return [super resolveInstanceMethod:sel];
}
@end

#在viewController中
- (void)viewDidLoad {
    [super viewDidLoad];
   
    Person *p = [[Person alloc]init];
    //performSelector:即为动态添加方法
    [p performSelector:@selector(eat)];
}
输出日志
#如果你要实现带有参数的(自己找两者的不同)

#Person.m文件中
// C语言中所有对象类型用 id
void tangtang_eat(id self, SEL _cmd, id prame1){
    
    NSLog(@"调用糖糖的eat方法 %@ %@ %@",self,NSStringFromSelector(_cmd),prame1);
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    
    // 动态添加未实现的方法
    if (sel == @selector(eat:)) {
        /**
         v : void
         @ : 对象
         : : SEL
         */
        class_addMethod(self, sel, (IMP)tangtang_eat, "v@:@");
       
        // 处理完
        return YES;
    }

    return [super resolveInstanceMethod:sel];
}

#ViewControllers中
 [p performSelector:@selector(eat:) withObject:@11];

输出日志,注意最后的11数字

添加方法完结,晚安,好梦

上一篇下一篇

猜你喜欢

热点阅读