RunTime简介
1.runtime是 OC 的底层实现, runtime API 都是纯 c 代码.
2.所有类中存在的东西,都可以用 runtime 来获得.
3.类:是给程序员看的, runtime: 转化成计算机能够看懂的东西.
Runtime基础介绍
1.获取属性
//通过runtime获得类中属性的列表
//就是返回的属性个数,也就是返回值的数组的count
unsigned int outCount;
objc_property_t * propertys = class_copyPropertyList(clazz, &outCount);
for(int i = 0; i < outCount;i++)
{
//取出具体的某一个属性
objc_property_t property = propertys[i];
//获得类属性的名称
const char * propertyName = property_getName(property);
//转换成oc字符串
NSString * propertyNameOC = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
//NSLog(@"%@",propertyNameOC);
//attributes 中获得重要信息
//1.属性的数据类型是什么
//2.属性与那个成员变量相关联
const char * attributes = property_getAttributes(property);
NSString * attributesString = [NSString stringWithCString:attributes encoding:NSUTF8StringEncoding];
//NSLog(@"%@",attributesString);
}
2.获取方法
unsigned int outCount;
//代表的就是方法
Method * methods = class_copyMethodList(clazz, &outCount);
for(int i = 0; i < outCount; i++)
{
Method method = methods[i];
SEL methodSEL = method_getName(method);
NSLog(@"%@",NSStringFromSelector(methodSEL));
}
3.获得类的所有成员变量
unsigned int outCount;
Ivar * vars = class_copyIvarList(clazz,&outCount);
for(int i = 0; i < outCount;i++)
{
Ivar var = vars[i];
NSString * varName = [NSString stringWithCString:ivar_getName(var) encoding:NSUTF8StringEncoding];
NSLog(@"varName %@",varName);
}
4.runtime调用方法
```
//1.调用哪个对象的
//2.什么方法
//3.什么参数
objc_msgSend(<#id self#>, <#SEL op, ...#>)
```
举例:
```
NSDictionary * dict = @{@"name":@"白成慧",@"age":@(24)};
Person * p = [[Person alloc] initWithDict:dict];
objc_msgSend(p, @selector(setAge:),20);
NSLog(@"%d",p.age);
```
Runtime 用法举例:
自己实现下KVC的两个重要的方法(虽然没什么意义,还是可以巩固下 runtime 的使用);
a. setValue: forKey
方法的实现:
- (void)my_setValue:(id)value forKey:(NSString *)key
{
//1.根据key值,把传递进来的value存储到对应的属性内部去
//把传递进来的key转化成set方法,然后执行该set方法进行赋值
//name
//1.set
//2.Namge:
//setName:
//把传递进来的key,首字母转换成大写,最终转换成符合set方法书写规则的字符串
NSString * propertName = [key capitalizedString];//Name Age Number Tmp
propertName = [NSString stringWithFormat:@"set%@:",propertName];
//在把符合规则的set方法字符串转换成SEL类型
SEL setSEL = NSSelectorFromString(propertName);
//判断一下,如果是包装类,就行特殊的处理
if([value isKindOfClass:[NSNumber class]])
{
objc_msgSend(self, setSEL,[value intValue]);
return;
}
//setName:
objc_msgSend(self, setSEL,value);
}
b.setValuesForKeysWithDictionary:
方法的实现:
- (void)my_setValuesForKeysWithDictionary:(NSDictionary *)keyedValues
{
for (int i = 0; i < keyedValues.allKeys.count;i++) {
NSString * key = keyedValues.allKeys[i];
id value = keyedValues.allValues[i];
[self my_setValue:value forKey:key];
}
}