objc/runtime 探索(一)

前言

最近闲来无事,打算对objc/runtime进行一番研究,今晚把API翻了一遍,拿出了如下的一些有趣代码,本代码需事先导入部分objc/runtime中的头文件,如下所示

#import <objc/runtime.h>  
#import <objc/message.h>

动态创建类

类的创建分为两步,添加成员变量需要在这两步操作之间,添加成员方法则无此要求

- `Class objc_allocateClassPair(Class superClass,const char* className,size_t extraBytes);`  
- `void objc_registerClassPair(Class cls);`  
//开始类的定义
Class Test= objc_allocateClassPair([NSObject class], "Test", 0);
//为类添加变量
class_addIvar(Test, "_name", sizeof(NSString*), log2(sizeof(NSString*)), @encode(NSString*));
//为类添加方法
//1.注册名为 test: 的方法
SEL s = sel_registerName("test:");
//2.定义函数实现,此处的IMP是函数指针,原型为 typedef id (*IMP)(id, SEL, ...);
IMP i = imp_implementationWithBlock(^(id this,id some){
    NSLog(@"%@",some);
    return @111;
});
//关联Test,s,i,并确认函数签名
class_addMethod(Test, s, i, "[email protected]:");
//结束类的定义
objc_registerClassPair(Test);

动态创建对象

采用上边代码创建的Test类创建对象,并通过该对象操作成员方法和成员变量

//创建对象
id t = [[Test alloc]init];
//KVC 动态改变 对象t 中的实例变量
[t setValue:@"张三" forKey:@"name"];
NSLog(@"%@",[t valueForKey:@"name"]);
//调用 t 对象中的 s 方法选择器对于的方法
id result = objc_msgSend(t, s,@"传送内容");
NSLog(@"%@",result);

运行结果

2014-08-15 00:11:00.239 Test[44644:303] 张三
2014-08-15 00:11:00.240 Test[44644:303] 传送内容
2014-08-15 00:11:00.241 Test[44644:303] 111