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

一, runtime的动态添加方法功能

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

  • 经典面试题 : 有没有使用过performSelector方法, 什么时候调用该方法?

    • 答 : 肯定是要回答使用过,不然就没有然后了........其实面试官主要是想问问你有没有动态添加过方法,下面我们就简单的学习runtime动态添加方法.
  • 2, 首先我们需要清除一个问题即: 为什么要动态添加方法,它的作用是什么,以及调用时刻是什么时候?

    答 : 在OC中,所有的控件(textFiled或者button等控件), 数组, 数据等都是以懒加载的形式加载的.真正使用的时候才会加载,或者添加方法.动态添加的方法的作用就是去处理未实现的实例方法或者是类方法.它的调用时刻: 只要我们调用了一个不存在的方法时,它就会动态添加方法.每个类都一个处理为实现方法的方法.

二, 步骤

  • 1, 新建一个学生类(WGStudent)在该类中只声明一个实例方法,不去实现,看看外界调用该方法时,会造成什么样的后果.

  • 下面这个方法是错误的演示


在 WGStudent.h文件中
#import <Foundation/Foundation.h>

@interface WGStudent : NSObject

// 如果该方法只有声明没有实现,那么该方法一定不会放在方法列表中,外界一定不能直接调用到方法
  - (void)study;

@end
在ViewController.h文件中
#import "ViewController.h"
#import "WGStudent.h"
#import <objc/message.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    WGStudent *student = [[WGStudent alloc] init];

    objc_msgSend(student, @selector(study));

}
@end
  • 打印结果
// 根本找不到这个方法
reason: '-[WGStudent study]: unrecognized selector sent to instance 0x7f94bb46e070'
  • 2, 这时候就需要使用到runtime动态添加方法了.在动态添加方法之前我们还需要判断当前的方法有没有实现,如果没有实现才需要动态添加方法.所以, 我们就需要了解下面两个方法:
// 动态去判断下eat方法有没有实现,如果没有实现,动态添加.
// 作用:处理未实现的对象方法
// 调用时刻:只要调用了一个不存在的对象方法就会调用
// sel:就是未实现方法编号

// 判断对象方法有没有实现
+(BOOL)resolveInstanceMethod:(SEL)sel

// 判断类方法有没有实现
+ (BOOL)resolveClassMethod:(SEL)sel

  • 3, 进入苹果系统内部查看如何动态添加方法(这是官方文档中的方法)
// dynamicMethodIMP方法
// 动态添加这个dynamicMethodIMP方法
void dynamicMethodIMP(id self, SEL _cmd) {
    // implementation ....
}

// 苹果内部的动态添加方法
@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
    if (aSEL == @selector(resolveThisMethodDynamically)) {
          class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
          return YES;
    }
    return [super resolveInstanceMethod:aSEL];
}
@end
  • 了解几个与动态添加方法有关的几个参数
// 参数解释:
        // Class;给哪个类添加方法
        // SEL:添加方法
        // IMP:方法实现,函数名
        // types:方法类型(不要去死记,官方文档中有)
class_addMethod(__unsafe_unretained Class cls, SEL name, IMP imp, const char *types)
  • 注意 : 动态添加方法的第三个参数是一个函数名,所以需要定义一个C语言函数,注意括号中的两个隐式参数,不能少,一下是给"学生类"动态添加方法,步骤都是按照苹果官方文档来创建的.
  • 2, 给学生动态添加一个学习英语的方法
在WGStudent.m文件中
// 模仿官方文档来动态添加方法
#import "WGStudent.h"
#import <objc/message.h>

@implementation WGStudent

void studyEngilsh(id self, SEL _cmd) {

    NSLog(@"动态添加了一个学习英语的方法");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {

    if (sel == NSSelectorFromString(@"studyEngilsh")) {
        // 注意:这里需要强转成IMP类型
        class_addMethod(self, sel, (IMP)studyEngilsh, "v@:");
        return YES;
    }
    // 先恢复, 不然会覆盖系统的方法
    return [super resolveInstanceMethod:sel];
}
@end

在ViewController.m文件中
#import "ViewController.h"
#import "WGStudent.h"
#import <objc/message.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    WGStudent *student = [[WGStudent alloc] init];

    [student performSelector:@selector(studyEngilsh)];
}
@end
  • 打印结果
// 说明动态添加方法成功
2016-03-08 20:07:23.160 sasass[1280:35172] 动态添加了一个学习英语的方法
  • 注意点:

  • 1, type(方法类型)用到时直接去官方文档中有详细的介绍
  • 2, C函数中两个隐式参数的意思 :
    • 1, self:方法调用者
    • _cmd:当前调用方法编号
    • 方法的隐式参数即: 没有暴露出来参数.

总结 : 不懂就去模仿官方文档,里面很详细

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,906评论 25 709
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,865评论 0 9
  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 9,101评论 7 64
  • 四天的学习,领略了本真教育的初衷,感受了二七一麾下峡山实验初中与峡山双语小学的办学风采,有收获,更有反思。但是最让...
    知北老师阅读 4,330评论 7 7
  • 打开一份公文,标题醒目,是“关于进一步做好**微信公众号订阅工作的通知”,这样的文件今年已经不是第一次收到。打开手...
    选择美好阅读 1,373评论 0 0

友情链接更多精彩内容