您的位置:首页 > 其它

runtime 系列-1.动态添加类及类属性 4000 ,并为类动态添加方法

2016-06-08 09:23 381 查看
本文主要是自己网上资料,根据上面的讲解的学习笔记.文章出处

在动态添加类及属性这块,主要用的的 runtime函数是

1).objc_allocateClassPair—–通过这个函数,可以创建出一个类

2).class_addIvar—–为该类添加实例变量

3).sel_registerName—–注册一个 SEL方法

4).class_addMethod—–为创建的类动态添加方法

5).objc_registerClassPair—–为创建的类进行注册

6).class_getInstanceVariable—–获取类中的实例变量

7).object_setIvar—–为对象中的变量赋值

8).objc_disposeClassPair—–销毁创建出来的类

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

void sayFunction(id self,IMP _cmd,id some){
//注意:这里的 self 其实是在调用该方法时候,传过来的 People 类
NSLog(@"%@岁的%@说:%@",object_getIvar(self, class_getInstanceVariable([self class], "_age")), [self valueForKey:@"name"],some);
}

int main(int argc, const char * argv[]) {
@autoreleasepool {
//动态创建对象
/**
*  该方法动态创建一个类
*
*  @param superclass#> 继承自哪一个类 description#>
*  @param name#>       name description#>
*  @param extraBytes#> extraBytes description#>
*
*  @return 返回一个对象
*/
Class People = objc_allocateClassPair([NSObject class], "Person", 0);

//为创建的这个类添加实例变量,在这里添加一个 name 的实例变量字符串和一个 int 类型的 age 实例变量
/**
*  第一个参数:为哪一个类添加实例变量
*  第二个参数:实例变量的名称
*  第三个参数:申请内存地址大小
*  第四个参数:实例变量的类型
*/
class_addIvar( People, "_name", sizeof(NSString *), log2(sizeof(NSString *)), @encode(NSString *));
class_addIvar(People, "_age", sizeof(int), sizeof(int), @encode(int));

//注册方法名
SEL s = sel_registerName("say:");

//为该类添加一个名为 say 的方法
/**
*  第一个参数:为哪个类添加方法
*  第二个参数:指定添加的 SEL 方法名
*  第三个参数:IMP是“implementation”的缩写,它是由编译器生成的一个函数指针。当你发起一个消息后(下文介绍),这个函数指针决定了最终执行哪段代码。
*  第四个参数:确定方法的参数及返回值
*/
class_addMethod(People, s, (IMP)sayFunction, "v@:@");

//注册该类
objc_registerClassPair(People);

//通过该类创建一个实体的对象
id peopleInstance = [[People alloc]init];

//给对象的 name 实例变量赋值
[peopleInstance setValue:@"苍老师" forKey:@"name"];

//获取类中的另外一个实例变量
/**
* 第一个参数:获取哪个类的实例变量
* 第二个参数:获取实例变量的名字
*/
Ivar ageIvar = class_getInstanceVariable(People, "_age");

//为对象中的实例变量赋值
/**
*  第一个参数:赋值对象
*  第二个参数:需要赋值的对象实例变量
*  第三个参数:该实例变量的值
*/
object_setIvar( peopleInstance, ageIvar, @18);

// 调用 peopleInstance 对象中的 s 方法选择器对应的的方法
// 推荐使用这个方法
/**
*  第一个参数:通过哪个对象调用方法
*  第二个参数:调用的哪个方法,在前面我注册了一个 s 的方法选择器
*  第三个参数:前面添加方法的时候,指定带有一个字符串的参数
*/
((void(*)(id, SEL, id))objc_msgSend)(peopleInstance, s, @"大家好");
//调用完成,将对象置为空
peopleInstance = nil;

//通过 objc 销毁类  销毁的是一个类不是对象
objc_disposeClassPair(People);
}
return 0;
}


我之前也看了很多关于 runtime 的文章,网上大多数都是根据理论来对 runtime 进行讲解的,比较空洞,也很难看下去,现在结合代码进行学习,理解起来更容易,也希望大家多多指教.工程代码在这里
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  runtime objc