runtime之所以非常强大,很关键的一点就是它能够动态地创建一个全新的类或对象。在runtime.h文件中可以查到动态创建一个类所涉及的所有函数。
/*创建一个新类或元类*/
objc_allocateClassPair(Class superclass,const char*name,size_t extraBytes)
/*注册一个通过objc_allocateClassPair方法创建的类*/
objc_registerClassPair(Class cls)
/*销毁一个类及其元类*/
objc_disposeClassPair(Class cls)
上面3个函数的作用见表。
动态创建类所涉及的3个函数
|
函数名
|
作 用
|
objc_allocateClassPair函数
|
它的作用是创建一个新类或元类。如果开发者想让这个类成为基类,那么参数superclass指 定为nil。参数extraBytes是分配给类和元类对象尾部的索引ivars的字节数,通常指定为0
|
objc_registerClassPair函数
|
当创建完新类后,需要调用这个方法来注册这个类,之后这个类才可以在程序中使用
|
objc_disposeClassPair函数
|
用于销毁一个类及其元类。需要注意的一点是,如果程序运行中还存在类或其子类的实例, 那么就不能调用该方法
|
那么,如何运用上述3个函数动态地添加一个类呢?示例代码如下:
/*创建一个新类myClass*/
Class myClass=objc_allocateClassPair([NSObject class],"myClass",0);
/*添加ivar*/
//@encode(aType):返回该类型的C字符串
class_addIvar(myClass,"_address",sizeof(NSString*),log2(sizeof(NSString*)),@encode(NSString*));
class_addIvar(myClass,"_age",sizeof(NSUInteger),log2(sizeof(NSUInteger)),@encode(NSUInteger));
/*注册类*/
objc_registerClassPair(myClass);
/*创建实例*/
id object=[[myClass alloc]init];
/*为ivar设置值*/
[object setValue:@"china"forKey:@"address"];
[object setValue:@20 forKey:@"age"];
NSLog(@"address=%@,age=%@",[object valueForKey:@"address"],[object valueForKey:@"age"]);
/*当类或者它的子类的实例还存在,则不能调用objc_disposeClassPair方法*/
object=nil;
/*销毁*/
objc_disposeClassPair(myClass);
程序的打印结果如下:
2016-11-02 19:32:39.615 01[67782:2681508]address=china,age=20
这样就通过运行时动态创建了一个继承自NSObject的myClass类,并为这个新类添加了address和age两个成员变量。特别需要注意的是,添加成员变量的方法class_addIva必须要在objc_allocateClassPair和objc_registerClassPair之间调用才行,这里涉及Objective-C中类的成员变量的偏移量,如果在类注册之后再调用class_addIva方法,那么会破坏原来类成员变量正确的偏移量,导致的后果就是会获取到错误的成员变量。