我们都知道,属性和成员变量在runtime中就是property和Ivar,研究runtime的话,理解并学会使用它们能让你灵活的操作类中的值.
Property
一个类的属性其实包含了3个我们知道的东西,分别是成员变量,setter和getter,但是我们怎么样能拿到他们呢?
首先先获取类的所有属性:
Class clazz = [self class];
unsigned int outCount = 0;
objc_property_t *propertyList = class_copyPropertyList(clazz, &outCount);
得到其一:
objc_property_t aproperty = propertyList[i];
得到属性名称和值:
NSString *pName = [NSString stringWithUTF8String:property_getName(aproperty)];
id pValue = [self valueForKey:pName];
得到属性的类型和对应的成员变量:
unsigned int attributeOutCount = 0;
objc_property_attribute_t *attributeList = property_copyAttributeList(aproperty, &attributeOutCount);
objc_property_attribute_t attribute = attributeList[i];
NSString *type; NSString *ivarName;
for (int j = 0; j<attributeOutCount; j++) {
objc_property_attribute_t attribute = attributeList[j];
NSString *atName = [NSString stringWithUTF8String:attribute.name];
NSString *atValue = [NSString stringWithUTF8String:attribute.value];
if ([atName isEqualToString:@"T"]) { type = atValue; }
if ([atName isEqualToString:@"V"]) { ivarName = atValue; }
}
简单解释一下,其中objc_property_attribute_t中有name和value,name有"T","C","N","V","&"等等一些不明的值,但通过相对应的value可以知道,"T"其实是type,即属性的类型,"V"则是成员变量名,其他几个我就不得而知了.
获取属性的setter和getter:
NSString *methodName = [NSString stringWithFormat:@"set%@%@:",[pName substringToIndex:1].uppercaseString,[pName substringFromIndex:1]];
SEL setter = sel_registerName(methodName.UTF8String);
SEL getter = sel_registerName(propertyName);
如果你想调用一下:
if ([objc respondsToSelector:setter]) {
((void (*)(id, SEL,id))(void *)objc_msgSend)(objc, setter,value);
}
注意:propertyList和attributeList最好free一下.
Ivar
得到所有的:
unsigned int ivarOutCount = 0;
Ivar *ivarList = class_copyIvarList(clazz, &ivarOutCount);
//每个变量其实都是Ivar类型的结构体
Ivar ivar = ivarList[i];
//变量名称
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
//变量的值
id value = [self valueForKey:ivarName];
//变量的类型
const char *type = ivar_getTypeEncoding(ivar);
网友评论