Get an object properties list in Objective-C

boliva picture boliva · Apr 16, 2009 · Viewed 66.4k times · Source

How can I get a list (in the form of an NSArray or NSDictionary) of a given object properties in Objective-C?

Imagine the following scenario: I have defined a parent class which just extends NSObject, that holds an NSString, a BOOL and an NSData object as properties. Then I have several classes which extend this parent class, adding a lot of different properties each.

Is there any way I could implement an instance method on the parent class that goes through the whole object and returns, say, an NSArray of each of the (child) class properties as NSStrings that are not on the parent class, so I can later use these NSString for KVC?

Answer

boliva picture boliva · Apr 16, 2009

I just managed to get the answer myself. By using the Obj-C Runtime Library, I had access to the properties the way I wanted:

- (void)myMethod {
    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];
        const char *propName = property_getName(property);
        if(propName) {
            const char *propType = getPropertyType(property);
            NSString *propertyName = [NSString stringWithCString:propName
                                                                encoding:[NSString defaultCStringEncoding]];
            NSString *propertyType = [NSString stringWithCString:propType
                                                                encoding:[NSString defaultCStringEncoding]];
            ...
        }
    }
    free(properties);
}

This required me to make a 'getPropertyType' C function, which is mainly taken from an Apple code sample (can't remember right now the exact source):

static const char *getPropertyType(objc_property_t property) {
    const char *attributes = property_getAttributes(property);
    char buffer[1 + strlen(attributes)];
    strcpy(buffer, attributes);
    char *state = buffer, *attribute;
    while ((attribute = strsep(&state, ",")) != NULL) {
        if (attribute[0] == 'T') {
            if (strlen(attribute) <= 4) {
                break;
            }
            return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
        }
    }
    return "@";
}