一、前言
本文主要记录如何用runtime 动态添加类 添加实例变量 添加方法等。项目中虽然很少用到,但是本着学习的态度,记录下来以便学习。
顺便给自己灌碗鸡汤:搞 iOS 学算法有意义吗?-唐巧。
本文Demo 地址:demo
二、切入正题
代码走一遍
1、 添加一个集成NSObject的类 类名是MyClass
注意:调用的c语言的方法 所以不要使用@""表示字符串 应该使用""
Class MyClass = objc_allocateClassPair([NSObject class], "MyClass", 0);
2、增加实例变量
参数一、类名
参数二、属性名称
参数三、开辟字节长度
参数四、对其方式
参数五、参数类型 “@” 官方解释 An object (whether statically typed or typed id) (对象 静态类型或者id类型) 具体类型可参照官方文档
return: BOOL 是否添加成功
BOOL isSuccess = class_addIvar(MyClass, "test", sizeof(NSString *), 0, "@");
// 三目运算符
isSuccess?NSLog(@"添加变量成功"):NSLog(@"添加变量失败");
3、增加方法
给MyClass这个类添加方法;
参数一、类名
参数二、SEL 添加的方法名字
参数三、IMP指针 (IMP就是Implementation的缩写,它是指向一个方法实现的指针,每一个方法都有一个对应的IMP)
参数四、其中types参数为"i@:@“,按顺序分别表示:具体类型可参照官方文档
i 返回值类型int,若是v则表示void
@ 参数id(self)
: SEL(_cmd)
@ id(str)
V@:表示返回值是void 带有SEL参数 (An object (whether statically typed or typed id))
class_addMethod(MyClass, @selector(addMethodForMyClass:), (IMP)addMethodForMyClass, "V@:");
4、这里我们需要实现一个函数和一个方法
函数 //self和_cmd是必须的,在之后可以随意添加其他参数
static void addMethodForMyClass(id self, SEL _cmd, NSString *test) {
// 获取类中指定名称实例成员变量的信息
Ivar ivar = class_getInstanceVariable([self class], "test");
// 获取整个成员变量列表
// Ivar * class_copyIvarList ( Class cls, unsigned intint * outCount );
// 获取类中指定名称实例成员变量的信息
// Ivar class_getInstanceVariable ( Class cls, const charchar *name );
// 获取类成员变量的信息
// Ivar class_getClassVariable ( Class cls, const charchar *name );
// 返回名为test的ivar变量的值
id obj = object_getIvar(self, ivar);
NSLog(@"%@",obj);
NSLog(@"addMethodForMyClass:参数:%@",test);
NSLog(@"ClassName:%@",NSStringFromClass([self class]));
}
5、我们要实现这个方法
//这个方法实际上没有被调用,但是必须实现否则不会调用addMethodForMyClass()方法
- (void)addMethodForMyClass:(NSString *)string {
}
6、接着第三步 开始创建MyClass对
id myObjc = [[MyClass alloc] init];
NSLog(@"%@",myObjc);
这个我们也可以通过发送消息创建对象
在OC中,我们对方法的调用都会被转换成内部的消息发送执行对objc_msgSend方法的调用,掌握好消息发送,可以让我们在编程中更方便灵活。
上面的id myObjc = [[MyClass alloc] init]; 我们可以通过runtime 消息发送objc_msgSend去实现
实现[MyClass alloc] 去开辟空间 并初始化
id myobjc = objc_msgSend(MyClass, @selector(alloc));
myobjc = objc_msgSend(myobjc, @selector(init));
下面我给属性test赋值
NSString *str = @"我是test";
// 通过KVC的方式给myObj对象的test属性赋值
[myobjc setValue:str forKey:@"test"];
// 如果不调用- (void)addMethodForMyClass:(NSString *)string 这个方法,就不会调用static void addMethodForMyClass(id self, SEL _cmd, NSString *test) 函数
[myobjc addMethodForMyClass:@"参数"];
通过上面的所有步骤 可以运行并且在函数addMethodForMyClass()打印确定这个类是不是创建成功
好了,今天就到这结束了,如果那里有错误,欢迎大家纠正!