然后在测试类中写一个测试函数testProperties调用上述两个函数得到其返回结果再分别依次遍历输出其返回值
执行上述测试函数后在控制台输出结果为:
从上述执行结果可以很好的说明前者只获取由@property声明的属性,而后者不但获取了@property属性,而且还获取了@interface大括号中声明的变量
typedef struct objc_property *Property;
您可以使用函数class_copyPropertyList和protocol_copyPropertyList来获得类(包括范畴类)或者协议类中的属性列表:
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
objc_property_t *protocol_copyPropertyList(Protocol *proto, unsigned int *outCount)
在使用这些方法的过程中,千万不要忘了一件事,那就是内存释放问题
容易造成这方面错误的有两种原因
一、当我们习惯了ARC的自动释放机制,所以会不经意的遗漏这方面的问题
记得在最后使用free来释放
二、大家在写代码的过程,基本都是网上搜索,参考已有的代码
而网上的代码有很大的问题,在代码的完整性方面有所欠缺,比如以下的代码:
上面的代码就缺少释放的功能,大家在借鉴时就会调入坑中
如何获取NSObject属性名和属性值的字典
- #import <Foundation/Foundation.h>
- #import <objc/runtime.h>
- @interface NSObject (PropertyListing)
- // aps suffix to avoid namespace collsion
- // ...for Andrew Paul Sardone
- - (NSDictionary *)properties_aps;
- @end
- @implementation NSObject (PropertyListing)
- - (NSDictionary *)properties_aps {
- NSMutableDictionary *props = [NSMutableDictionary dictionary];
- unsigned int outCount, i;
- objc_property_t *properties = class_copyPropertyList([self class], &outCount);
- for (i = 0; i < outCount; i++) {
- objc_property_t property = properties[i];
- NSString *propertyName = [[[NSString alloc] initWithCString:property_getName(property)] autorelease];
- id propertyValue = [self valueForKey:(NSString *)propertyName];
- if (propertyValue) [props setObject:propertyValue forKey:propertyName];
- }
- free(properties);
- return props;
- }
- @end
- // The Person class has `firstName` and `lastName`
- // properties.
- // andrew is a Person instance with NSString values
- // of "Andrew" and "Sardone" for `firstName` and
- // `lastName` respectively.
- NSString *jsonString = [[andrew properties_aps]
- JSONRepresentation];
- // now `jsonString` looks like:
- // { "firstName": "Andrew", "lastName": "Sardone" }
- (void)copyProperty:(ViewModel *)dst cls:(Class)cls
{
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(cls, &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:propName];
id val = [self valueForKey:propertyName];
//这里的respondsToSelector:NSSelectorFromString([self getSetterName:propertyName])中给的是setProperty方法,而不是一个property属性字符串。
if ((val) && ([dst respondsToSelector:NSSelectorFromString([self getSetterName:propertyName])]))
{
[dst setValue:val forKey:propertyName];
}
}
free(properties);
if ([cls superclass] != [NSObject class])
{
[self copyProperty:dst cls:[cls superclass]];
}
}
- (ViewModel *)clone
{
ViewModel *newModel = [[self.class alloc] init];
[self copyProperty:newModel cls:self.class];
return newModel;
}
/** 将属性名转换成属性的Setter名,形成set方法 */
-(NSString *)getSetterName:(NSString *)propName{
NSString *capitalisedSentence = [propName stringByReplacingCharactersInRange:NSMakeRange(0,1)
withString:[[propName substringToIndex:1] capitalizedString]];
NSString *setterName = [NSString stringWithFormat:@"set%@:", capitalisedSentence];
return setterName;
}
本文探讨了Objective-C Runtime中的`class_copyPropertyList`和`class_copyIvarList`的区别。前者用于获取使用@property声明的属性,而后者不仅包括@property属性,还包括@interface中的变量。在使用这些方法时,需要注意内存释放问题,避免因遗忘释放而引发错误。示例代码展示了如何遍历并复制对象的属性到另一个实例中。

被折叠的 条评论
为什么被折叠?



