
1.API
To create a new class, start by calling objc_allocateClassPair. Then set the class’s attributes with functions like class_addMethod and class_addIvar. When you are done building the class, call objc_registerClassPair. The new class is now ready for use.
Instance methods and instance variables should be added to the class itself. Class methods should be added to the metaclass.
1.1.增加类
1 |
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes); |
这两个方法应该配对使用,在二者之间增加成员变量、属性、实例方法和类方法等。调用第二个方法即注册类,这之后类的结构也就固定下来,不能再向类中增加新的成员变量,但是可以增加属性和方法。其中后续增加的属性不会自动生成_属性名成员变量,也不会提供属性的setter与getter函数及其实现。
1.2.增加方法
1 |
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types); |
- 实例方法应该加到当前实例的isa指向的类中;
- 类方法则应该加到当前类的元类中;
1.3.增加成员变量
1 |
BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types); |
This function may only be called after objc_allocateClassPair and before objc_registerClassPair. Adding an instance variable to an existing class is not supported.
The class must not be a metaclass. Adding an instance variable to a metaclass is not supported.
新增成员变量应该在类注册完成之前进行,类注册完成之后类结构已固定,实例的内存空间已经确定,不能再增加新的成员变量。
新增加的成员变量应该加到实例对象所属的类中,而不能加到其所属类的元类中。
1.4.增加属性
1 |
BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount); |
2.示例
1 |
#import "AppDelegate.h" |
其中RuntimeTool是工具类,用来获取成员变量、属性和方法列表,实现代码如下:
1 |
#import "RuntimeTool.h" |
注意:直接调用objc_msgSend在编译时会报错,需要在 “Build Setting”中,把“ Enable Strict Checking of objc_msgSend Calls” 关掉。
示例运行后输出日志:
1 |
+++++成功添加成员变量'height'~ |
从日志中也可以得出结论:
1、在类allocate与register之间可以添加成员变量、属性和方法;
2、在register之后,即类结构固定之后不能再添加成员变量,但可以继续添加属性和方法;
3、动态添加的属性,并不会创建其对应的以_开头的成员变量,实际上这一步需要由编译器来完成。
ps: 热更新JSPatch就是在OC的 runtime 基础上实现的,大致原理是:JS传递字符串给OC,OC通过 Runtime 的运行时函数,调用和替换相应的OC方法。待后期慢慢研究。。




近期评论