Is there a way to loop through all properties in an object and get their \"name\" and \"value\".
I am trying to write a category to serialize objects to a string, ba
I don't have comment privileges yet, but to add to @Costique's answer, there is an additional attribute Type value "V" which is the name of the IVar to which a property may be bound (via synthesize). This can be readily discovered with this
@interface Redacted : NSObject
@property (atomic, readonly) int foo;
@end
@implementation Redacted
@synthesize foo = fooBar;
@end
// for all properties
unsigned propertyCount = 0;
objc_property_t *properties = class_copyPropertyList([object class], &propertyCount);
for (int prop = 0; prop < propertyCount; prop++)
{
// for all property attributes
unsigned int attributeCount = 0;
objc_property_attribute_t* attributes = property_copyAttributeList(property, &attributeCount);
for (unsigned int attr = 0; attr < attributeCount; attr++)
{
NSLog(@"Attribute %d: name: %s, value: %s", attr, attributes[attr].name, attributes[attr].value);
}
}
2013-07-08 13:47:16.600 Redacted5162:303] Attribute 0: name: T, value: i
2013-07-08 13:47:16.601 Redacted[5162:303] Attribute 1: name: R, value:
2013-07-08 13:47:16.602 Redacted[5162:303] Attribute 2: name: V, value: fooBar
Maybe class_copyPropertyList()
will do what you are after - but notice that it only returns declared properties.
Not all properties are declared - NSDictionary
and NSMutableDictionary
are examples of classes where you can set properties that are not declared in the class.
More in the docs.
You can use this code to enumerate all properties declared in a class, and all attributes of the properties. I guess you're more interested in parsing the type attribute. They are detailed here.
unsigned int numOfProperties;
objc_property_t *properties = class_copyPropertyList([self class], &numOfProperties);
for ( unsigned int pi = 0; pi < numOfProperties; pi++ ) {
// Examine the property attributes
unsigned int numOfAttributes;
objc_property_attribute_t *propertyAttributes = property_copyAttributeList(properties[pi], &numOfAttributes);
for ( unsigned int ai = 0; ai < numOfAttributes; ai++ ) {
switch (propertyAttributes[ai].name[0]) {
case 'T': // type
break;
case 'R': // readonly
break;
case 'C': // copy
break;
case '&': // retain
break;
case 'N': // nonatomic
break;
case 'G': // custom getter
break;
case 'S': // custom setter
break;
case 'D': // dynamic
break;
default:
break;
}
}
free(propertyAttributes);
}
free(properties);
I use the following Category on NSObject
to say, for example, NSLog(@"%@", [someObject propertiesPlease]);
, resulting in a log entry like…
someObject: {
color = "NSCalibratedRGBColorSpace 0 0 1 1";
crayon = Blueberry;
}
NSObject+Additions.h
@interface NSObject (Additions)
- (NSDictionary *)propertiesPlease;
@end
NSObject+Additions.m
@implementation NSObject (Additions)
- (NSDictionary *)propertiesPlease {
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)];
id propertyValue = [self valueForKey:(NSString *)propertyName];
if (propertyValue) [props setObject:propertyValue forKey:propertyName];
}
free(properties);
return props;
}
@end