美文网首页
runtime之动态添加方法

runtime之动态添加方法

作者: melody5 | 来源:发表于2018-05-29 17:24 被阅读14次

如果一个类接收到一个没有实现的实例方法,就会进到下面这个方法里+(BOOL)resolveInstanceMethod:(SEL)sel,同理类方法会进到这个+(BOOL)resolveClassMethod:(SEL)sel

1. 验证

首先创建一个Student类然后调用一个没实现的learn方法:

    Student *s = [[Student alloc] init];
    [s performSelector:@selector(learn)];

然后在Student.m中拦截一下,打印方法名:

// 如果该类接收到一个没有实现的实例方法,就会进到这个方法里
+(BOOL)resolveInstanceMethod:(SEL)sel {
    NSLog(@"%@",NSStringFromSelector(sel));
    return [super resolveInstanceMethod:sel];
}

打印

runtime_动态添加方法[2398:288368] learn

2. 动态添加方法

接下来,拦截到以后动态添加一个方法,用runtime的class_addMethod方法

// 动态添加方法
    /*
     1、cls 给哪个类添加方法
     2、SEL 方法编号
     3、IMP 函数指针
     4、返回值类型
     */
    class_addMethod(<#Class  _Nullable __unsafe_unretained cls#>, <#SEL  _Nonnull name#>, <#IMP  _Nonnull imp#>, <#const char * _Nullable types#>)

前边三个参数都好理解,关于第四个参数,苹果的文档里有介绍,command+shift+0打开文档,搜索class_addMethod,下面是示例代码和截图

class_addMethod([self class], @selector(resolveThisMethodDynamically), (IMP) myMethodIMP, "v@:");
image.png

然后在resolveInstanceMethod动态添加一个方法,在用speak方法接收处理:

+(BOOL)resolveInstanceMethod:(SEL)sel {
    
    NSLog(@"%@",NSStringFromSelector(sel));
    // 动态添加方法
    class_addMethod(self, sel, (IMP)speak, "v@:");
    
    return [super resolveInstanceMethod:sel];
}

void speak() {
    NSLog(@"speak");
}

打印

runtime_动态添加方法[2430:292288] learn
runtime_动态添加方法[2430:292288] speak

动态创建方法成功

3. 传参数

OC的方法调用,会默认传递两个隐式参数给IMP(方法实现),文档里有示例代码,截图


image.png

首先调用时传个参数:

    Student *s = [[Student alloc] init];
    [s performSelector:@selector(learn) withObject:@"English"];

也可以换成发送消息(这里不懂可以看我之前的关于消息转发的简书),这里的参数和我们接收时的参数是一一对应的,便于理解

    Student *s = [[Student alloc] init];
    objc_msgSend(s, sel_registerName("learn"), @"English");

这里class_addMethod函数的第四个参数需要改成"v@:@",接收的speak函数需要把隐式参数都加上,才可以收到我们传的参数:

// 如果该类接收到一个没有实现的实例方法,就会进到这个方法里
+(BOOL)resolveInstanceMethod:(SEL)sel {
    
    NSLog(@"%@",NSStringFromSelector(sel));
    // 动态添加方法
    class_addMethod(self, sel, (IMP)speak, "v@:@");
    
    return [super resolveInstanceMethod:sel];
}

/**
 OC的方法调用,会默认传递两个隐式参数给IMP(方法实现)
 objc_msgSend(self,_cmd)
 id self  方法的调用者
 SEL _cmd 方法编号
 */
void speak(id class, SEL sel, NSString *objc) {
    NSLog(@"%@-%@-%@",NSStringFromClass([class class]),NSStringFromSelector(sel),objc);
}

打印

runtime_动态添加方法[2458:295930] learn
runtime_动态添加方法[2458:295930] Student-learn-English

对照一下发消息和接收函数的参数:

// 发消息
objc_msgSend(s, sel_registerName("learn"), @"English");
// 接收函数
void speak(id class, SEL sel, NSString *objc)

完!!!

相关文章

  • runtime的理解(二)

    主要内容 利用 runtime 交换方法 利用 runtime 动态添加方法 利用 runtime 动态添加属性 ...

  • runtime

    runtime交换方法 动态添加方法

  • 自己实现OC的KVO

    Runtime系列文章在这:Runtime介绍---术语介绍Runtime应用--动态添加方法Runtime应用-...

  • runtime和oc内存区域(2018-04-02)

    runtime常用的几个方法: 交换方法 动态添加属性 动态添加方法 1.交换方法 class_getClassM...

  • IOSRunTime_动态添加方法

    利用RunTime运行时,动态添加一个方法 动态添加方法,首先实现这个resolveInstanceMethod ...

  • runTime之--动态添加方法

    Runtime运行时之--动态添加方法 - OC都是懒加载机制、只要方法实现了,就会马上添加到方法列表List中-...

  • runtime相关

    修改系统方法 动态添加方法 动态给系统类添加属性(给分类添加属性) runtime+kvc 转换模型

  • runtime简单使用之动态添加方法

    一, runtime的动态添加方法功能 1, 关于runtime动态添加方法,我们以一个经典的面试题展开对其的研究...

  • runtime之动态添加方法

    如果一个类接收到一个没有实现的实例方法,就会进到下面这个方法里+(BOOL)resolveInstanceMeth...

  • runtime之动态添加方法

    需求:runtime 动态添加方法处理调用一个未实现的方法 和 去除报错。 案例代码 IMP 代码中已附个人整理。...

网友评论

      本文标题:runtime之动态添加方法

      本文链接:https://www.haomeiwen.com/subject/kteajftx.html