Objective- C - Looping through all properties in a class?

后端 未结 4 1994
清酒与你
清酒与你 2020-12-14 03:09

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

相关标签:
4条回答
  • 2020-12-14 03:27

    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

    0 讨论(0)
  • 2020-12-14 03:47

    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.

    0 讨论(0)
  • 2020-12-14 03:48

    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);
    
    0 讨论(0)
  • 2020-12-14 03:48

    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
    
    0 讨论(0)
提交回复
热议问题