这篇文章是我自己学习runtime时候的笔记,水平有限有需要补充或者指正的地方,希望提出来,大家一起学习
一.Runtime的含义
- Runtime 是一套由C,C++及汇编语言组成的提供给Objective-C(简写OC)_运行时_使用的API
我们知道OC程序运行的过程分为编译->链接->运行等几个步骤,OC语言尽可能的把一些操作推迟到运行时,动态的处理一些问题。
- Runtime 在三种层面上与 OC 系统进行交互:
- 通过 Objective-C 源代码间接使用Runtime
- 通过 Foundation 框架的 NSObject 类定义的方法
- 通过对 Runtime API的直接调用
- Runtime的常用应用
- 消息转发
- 方法交换( Method swizzling)
- 动态的添加类对象的成员变量和方法,分类中添加属性
- 获取某个类的所有成员变量和成员方法
- 实现字典模型的自动转换
- 防止程序crash 等
二.对象与方法的本质
- 查看对象和方法的本质之前,我们需要准备
-
Clang编译器的使用
- 对象的本质探索
创建工程 ->创建MRPerson类,打开终端,cd到工程地址根目录下,输入命令:clang -rewrite-objc main.m -o test.cpp,在文件夹中我们可以看到test.cpp的生产文件
如图:
打开text.cpp文件-> 拉到最底部main函数部分可以看到
搜索test.app文件中的MRPerson类,如下图
对象MRPerson是objc_object的结构体,所以我们可以得到这样的结论:OC对象的本质是结构体
- 方法的本质探索
在test.app文件中,除了objc_getClass外还有一行objc_msgSend
如上图我们可以得出这样的一个结论:方法的本质是发送消息
- 类方法与实例方法
直接调用Runtim API 的objc_msgSend()方法,会报“Implicit declaration of function 'objc_msgSend' is invalid in C99”错误.所以应该在main函数文件中导入**#include <objc/message.h>**头文件,才能使用Runtime API的方式查看类方法和实例方法的具体实现
小知识点:#include,#import,@class的区别:
1.#import是object-c导入头文件的关键字,#include是C/c++导入头文件的关键字
2.使用#import导入头文件会自动只导入一次,不会重复导入
3.@class是告诉编译器某个类的声明,当执行时,才会去查看类的实现文件,可以解决头文件的相互包含
4.#import <>用来包含系统的头文件,#import ""是包含用户的头文件。
调取objc_msgSend(id _Nullable self, SEL _Nonnull op, ...) 方法出现
错误,需要在xcode->Build Settings 设置为NO:
类方法与实例方法具体实现(父类,元类,基类)
上图可看出:
-
当发送消息给实例对象时,消息是在寻找这个对象的类的方法列表(实例方法)
-
当发送消息给类对象时,消息是在寻找这个类的元类的方法列表(类方法)
对象在类中以实例的方式存储
类在元类中也是以实例的方式存储