How to dynamically determine Objective-C property type?

I’m trying to dynamically determine the type of a property in Objective-C. Based on what I have read on this site and elsewhere, I believe I am doing the right thing. However, my code isn’t working.

The code snippet below demonstrates the problem. Attempting to get the property information for “backgroundColor” and “frame”, both of which are valid properties of UIView, fails (class_getProperty() returns NULL):

  • Objective C: Why do we declare ivars in the .h member area if @property seems to do it automatically?
  • Swift: Why cannot add store property in extension? What's the different between store property and computed property in memory
  • Is there a way to log all the property values of an Objective-C instance
  • Property vs. ivar in times of ARC
  • Do private ivars in Objective-C have atomic attribute by default (like properties)?
  • iOS — “add” methods appearing for autosynthesized properties in codeSense
  • id type = [UIView class];        
    objc_property_t backgroundColorProperty = class_getProperty(type, "backgroundColor");
    fprintf(stdout, "backgroundColorProperty = %d\n", (int)backgroundColorProperty); // prints 0
    
    objc_property_t frameProperty = class_getProperty(type, "frame");
    fprintf(stdout, "frameProperty = %d\n", (int)frameProperty); // prints 0
    

    Enumerating the properties as described here doesn’t produce the expected results, either. The following code:

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

    generates this output:

    2012-03-09 13:18:39.108 IOSTest[2921:f803] Properties for UIView
    caretRect T{CGRect={CGPoint=ff}{CGSize=ff}},R,N,G_caretRect
    gesturesEnabled Tc,N
    deliversTouchesForGesturesToSuperview Tc,N
    skipsSubviewEnumeration Tc,N
    viewTraversalMark Tc,N
    viewDelegate T@"UIViewController",N,G_viewDelegate,S_setViewDelegate:
    inAnimatedVCTransition Tc,N,GisInAnimatedVCTransition
    monitorsSubtree Tc,N,G_monitorsSubtree,S_setMonitorsSubtree:
    backgroundColorSystemColorName T@"NSString",&,N,G_backgroundColorSystemColorName,S_setBackgroundColorSystemColorName:
    userInteractionEnabled Tc,N,GisUserInteractionEnabled
    tag Ti,N,V_tag
    layer T@"CALayer",R,N,V_layer
    

    Documented properties such as “backgroundColor”, “frame”, and others are missing, whereas undocumented properties like “caretRect” and “gesturesEnabled” are included.

    Any help would be very much appreciated. In case it is relevant, I’m seeing this behavior on the iOS simulator. I don’t know if the same thing would happen on an actual device.

    Thanks,
    Greg

    3 Solutions Collect From Internet About “How to dynamically determine Objective-C property type?”

    You are getting the UIView properties, the problem is backgroundColor is not a UIView property, is a category property. Check UIView.h. I think you can’t get a objc_category, but have a look at class-dump.

    Dodging around the issue slightly, the following works:

    NSMethodSignature *signature = [[UIView class] 
                instanceMethodSignatureForSelector:@selector(backgroundColor)];
    NSLog(@"%s", [signature methodReturnType]);
    

    So the runtime may somehow have lost the fact that backgroundColor is a property but you seem to start with that information anyway in the first code snippet so it just checks out the return type of the getter.

    You can find category properties as methods.

    @import ObjectiveC;
    
    static void test(Class class, NSString* methodName) {
    
        Method method = class_getInstanceMethod(class, NSSelectorFromString(methodName));
    
        const char* type = method_copyReturnType(method);
    
        printf("%s : %s\n", methodName.UTF8String, type);
    
        free((void*)type);
    }
    

    Then you inspect some…

    test([UILabel class], @"alpha");
    test([UILabel class], @"textColor");
    test([UILabel class], @"isHidden");
    test([UILabel class], @"minimumScaleFactor");
    

    After look at these defines in runtime.h

    #define _C_ID       '@'
    #define _C_CLASS    '#'
    #define _C_SEL      ':'
    #define _C_CHR      'c'
    #define _C_UCHR     'C'
    #define _C_SHT      's'
    #define _C_USHT     'S'
    #define _C_INT      'i'
    #define _C_UINT     'I'
    ...
    

    Don’t forget to respect getters/setters notation for BOOL properties, search ‘isHidden’ instead ‘hidden’.