Runtime(一) 初识runtime

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shaohua_lv/article/details/70316855

iOS开发中的runtime被称为黑魔法,本节就向大家讲解什么是runtime.

runtime 是属于OC底层的实现,可以进行一些OC无法操作的事情
1.利用Runtime,在程序运行时,动态加载一个类
2.利用Runtime,在程序运行时,动态修改类的属性,方法
3.利用Runtime遍历一个类的所有属性
……(总之很强大)

接下来我会一步一步展示下什么是runtime,

一、首先配置下测试环境

首先我们新建一个工程,X-code5.0之后苹果不建议使用底层代码,如果使用runtime方法,需要在buildSetting中做修改。如下所示:将objc_msgSend检测设为禁用。

这里写图片描述

接着我们新建一个Person类,声明并实现eat方法:

这里写图片描述

二、我们先看下传统的方法调用都有哪些:

我们可以使用传统的方法调用如下,相信大家都经常用到

  Person *person = [[Person alloc] init];

    // 1.OC语法的方法调用。
    [person eat];

    // 2.用performSelector调用
    [person performSelector:@selector(eat)];

三、接下来我们使用runtime来调用

引入头文件:#import < objc/message.h> 或 #include < objc/runtime.h> 前者包括后者。

    Person *person = [[Person alloc] init];    

    // 3.使用runtime调用
    objc_msgSend(person, @selector(eat));

同样打印信息如下:

2017-04-21 14:34:28.891 Runtime[38675:3227119] enter person eat

我们详解下:

objc_msgSend(<#id self#>, <#SEL op, ...#>)

我们OC的方法调用的消息发送机制可以在这里得到答案,每一个方法,其实都是对一个对象发送一个消息。
id self : 发送消息的对象。
<#SEL op, …#>:发送什么消息,后面…就代表可扩展参数,如果方法需要入参的话可做扩展,就像NSLog(<#NSString * _Nonnull format, …#>)扩展参数用法一样。

另外:@selector方法选择器在runtime时被替换成:sel_registerName

所以方法进一步底层化为:

objc_msgSend(person, sel_registerName("init"))

四、msgSend还可以做哪些事?

上面一个简单的展示,可以用这个方法来代替方法调用,支持方法有多个入参,那么

Person *person = [[Person alloc] init]

可以使用类似方法吗?答案是可以的。
我们一步一步拆分得到:
1、

Person *person = [Person alloc];

我们可以使用runtime的另一个objc_getClass(“Person”),得到类的名字,再调用alloc:

objc_msgSend(objc_getClass("Person"), @selector(alloc))

2、

[person init];

我们可以直接这样做:
objc_msgSend(person, @selector(“init”));

总结整理后我们可以吧person的初始化方法替换为runtime语言:

objc_msgSend(objc_getClass("Person"), sel_registerName("alloc"),sel_registerName("init"));

五、编译文件,查看真实的runtime

读者可能会问:我该怎么证明这些都是正确的呢?相信看完下面就明白了。

1、我们新建一个Command Line工程,注意一定要是这样的工程,因为这里不会因人UIKit框架,笔者能力有限,暂不会编译那种文件。

2、新建一个Person类,同样声明实现eat方法:

这里写图片描述

3、我们在控制台用clang指令编译main.m文件:

这里写图片描述

4、在同级目录生成了个main.cpp文件,这个就是我们想要的:

这里写图片描述

5、打开main.cpp我们看文件的最下边:

这里写图片描述

怎么样,相信了吧,我们的每个方法在编译时候都会被编译成runtime运行时语言,他能帮助我们做很多强大功能。

接下来在后面博客中,我会使用实际案例,帮助大家更深刻的理解runtime。

猜你喜欢

转载自blog.csdn.net/shaohua_lv/article/details/70316855