我們都知道,屬性和成員變量在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);
如果你想調(diào)用一下:
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);