Runtime 是一套比较底层的纯C语言API 它是OC的幕后工作者 我们平时写的OC代码 ,在运行时都会编译器转为runtime的C语言代码 其中最主要的是消息机制OC的函数调用,成为消息发送 属于动态调用过程 在编译的时候并不能决定真正调用哪个函数事实证明,在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错,而C语言在编译阶段就会报错 只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。
RunTime可以动态的给对象的属性赋值,还可以修改属性;
简单的运行时
Class BGCls = NSClassFromString(@"Bigbang");
id Top = [[BGCls alloc] init];
[cat1 performSelector:@selector(setName:) withObject:@"GD"];
NSLog(@"name:%@",[Top valueForKey:@"name"]);
首先通过obj的isa指针找到obj对应的class。在Class中先去cache中 通过SEL查找对应函数method—cache中method列表是以key通过hash表来存储的,这样能提高函数查找速度),若 cache中未找到。再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加 入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中
RunTime可以动态的添加一个类,它会通过类名获取类,如果类不存在就会创建需要运行类父类,我们可以通过指定协议(Protocol)的方式
运行如何添加一个类
// 设置类名
const char * className = "MyClass";
// 通过类名获取类
Class kclass = objc_getClass(className);
// 如果类不能存在
if (!kclass)
{
// 创建需要运行类父类
Class superClass = [NSObject class];
// 创建类
kclass = objc_allocateClassPair(superClass, className, 0);
}
// 3. 对类添加方法
IMP myIMP = imp_implementationWithBlock(^(id _self, NSString *string) {
NSLog(@"Hello %@", string);
});
// @encode(float) 用这个关键字可以获取 参数类型
class_addMethod(kclass, @selector(sayHello:), myIMP, "v@:@");
// 添加成员变量
// class_addIvar
// 添加关联属性
// class_addProperty
// 添加协议
// class_addProtocol
// 注册类
objc_registerClassPair(kclass);
// 如何获取内存中所有的OC类
// 类的数量
int numClasses;
// 存放指向第一个类的指针
Class *classes = NULL;
// 获取多少类
numClasses = objc_getClassList(NULL, 0);
// 如果获取的类大于0
if(numClasses > 0) {
// 为获取所有的类开辟内存
classes = (Class *)malloc(sizeof(Class) * numClasses);
// 把所有类拷贝到我开的内存中
numClasses = objc_getClassList(classes, numClasses);
// 遍历所有的类
for (NSInteger i = 0; i < numClasses; i++)
{
Class cls = classes[i];
// NSLog(@"class name:%@",NSStringFromClass(cls));
//通过类名检索我们需要找的类
/*
if([NSStringFromClass(cls) isEqualToString:@"MyClass"]) {
NSLog(@"找到了MyClass");
}*/
// 通过协议来查找我们需要的类
if(class_conformsToProtocol(cls, @protocol(AnimationProtocol))) {
id<AnimationProtocol> instance = [[cls alloc] init];
[instance test];
}
}
free(classes);
}
NSLog(@"numClasses:%d",numClasses);
==================华丽的分割线来了======================
NSMutableArray* intercepterClasses = [NSMutableArray array];
int numClasses;
Class * classes = NULL;
classes = NULL;
numClasses = objc_getClassList(NULL, 0);
if (numClasses > 0 )
{
Protocol* aopProtocol = @protocol(ZWIntercepterProtocol);
classes = (Class *)malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);
for (NSInteger i = 0; i < numClasses; i++)
{
Class cls = classes[i];
for ( Class thisClass = cls; nil != thisClass ; thisClass = class_getSuperclass( thisClass ) )
{
if(class_conformsToProtocol(thisClass, aopProtocol)) {
[intercepterClasses addObject:cls];
}
}
}
free(classes);
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
Class myCls = NSClassFromString(@"MyClass");
id instance = [[myCls alloc] init];
[instance performSelector:@selector(sayHello:) withObject:@"Hi"];
NSLog(@"%@",myCls);
}