views:

727

answers:

1

I tried to list all properties of an Objective-C class like described in the Objective-C 2.0 Runtime Programming Guide:

id LenderClass = objc_getClass("UIView");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(LenderClass, &outCount);
for (i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}

But this lists only three properties:

userInteractionEnabled Tc,GisUserInteractionEnabled
layer T@"CALayer",R,&,V_layer
tag Ti,V_tag

Looking at the header file for UIView.h those are the three properties directly declared in the class. The other UIView properties are added through categories.

How do I get all properties of a class, including those coming from categories?

I tried this with the iPhone simulator (iPhone SDK 2.2.1), btw. (in case this is important).

+3  A: 

Based on my tests here, properties from categories will show up when using class_copyPropertyList. It looks as though the properties you're seeing on UIView are only described as properties in the public headers, not actually declared as such when building the UIKit itself. Probably they adopted the property syntax to make the creation of the public headers a little quicker.

For reference, here's my test project:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface TestClass : NSObject
{
    NSString * str1;
    NSString * str2;
}
@property (nonatomic, copy) NSString * str1;
@end

@interface TestClass (TestCategory)
@property (nonatomic, copy) NSString * str2;
@end

@implementation TestClass
@synthesize str1;
@end

@implementation TestClass (TestCategory)

// have to actually *implement* these functions, can't use @synthesize for category-based properties
- (NSString *) str2
{
    return ( str2 );
}

- (void) setStr2: (NSString *) newStr
{
    [str2 release];
    str2 = [newStr copy];
}

@end

int main (int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList([TestClass class], &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
    }

    [pool drain];
    return 0;
}

And here's the output:

str2 T@"NSString",C
str1 T@"NSString",C,Vstr1
Jim Dovey
Thanks a lot for the answer. It really looks like something is special about the UIKit in this respect. But your example actually does not show this since it works as expected; i.e. it lists the str2 property (which is more than I get with UIView).
ashcatch
This is what I meant, above. The properties declared in the public headers for UIView aren't actually declared as properties in the source used to build the UIKit, so they're not actually stored as such in the ObjC runtime information in the binary. i.e. there are a bunch of getter/setter methods, and for the public headers they've just added property declarations instead of method declarations for brevity. If they really were properties, they would show up via class_copyPropertyList(), even if they were declared in categories.
Jim Dovey