Question

Since property named "age" would always have a selector named "age" as well, I could use respondsToSelector as this question suggests and that will tell me if a particular selector exists at runtime in any given object.

If a property named "age" exists, I can verify that. How could I know if that selector (the read method for that property) returns an object (id) or non-object (int)?

Is such type determination possible at runtime, or is the Objective-C way to always assume that someone implemented that method using the type I'm hoping it used, or can I also verify the return type?

This is using the latest Objective-C version (LLVM 4.1) in XCode 4.5.

Update: This is the utility-category-on-NSObject that I came up with:

   - (NSString*) propertyType: (NSString*)propname
{
    objc_property_t aproperty = class_getProperty([self class],  [propname cStringUsingEncoding:NSASCIIStringEncoding] ); // how to get a specific one by name.
    if (aproperty)
    {
     char * property_type_attribute = property_copyAttributeValue(aproperty, "T");
     NSString *result = [NSString stringWithUTF8String:property_type_attribute];
     free(property_type_attribute);
     return result;
    }
    else
        return nil;
}

While looking into this question I also wrote this handy-dandy utility method that can list all the properties on this object:

- (NSArray*) properties;
{
    NSMutableArray *results = [NSMutableArray array];
    @autoreleasepool {

        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 * aname=property_getName(property);
            [results addObject:[NSString stringWithUTF8String:aname]];
            //const char * attr= property_getAttributes(property);
            //[results addObject:[NSString stringWithUTF8String:attr]];

        }
        if (properties) {
            free(properties);
        }

  } // end of autorelease pool.
  return results;
}
Was it helpful?

Solution 2

One approach you can take, assuming you know the property name already, is to use the class_getProperty function. You can also use the property_copyAttributeValue() function to get just a particular attribute by name:

objc_property_t number_property = class_getProperty([MyClass class], "number");
char *number_property_type_attribute = property_copyAttributeValue(number_property, "T");
NSLog(@"number property type attribute = %s", number_property_type_attribute);

Will log:

2013-01-14 14:45:37.382 RuntimeFun[61304:c07] number property type attribute = i

Assuming MyClass looks something like:

@interface MyClass : NSObject
@property (nonatomic) int number;
@end

@implementation MyClass
@end

One you have your type attribute string, you can then compare it to the various Objective-C type encodings. Once you're done with your comparison, be sure to call free() on your attribute string.

OTHER TIPS

You could use class_copyPropertyList to get a list of properties declared in a class.

class_copyPropertyList

Describes the properties declared by a class.

And then property_getAttributes:

property_getAttributes

Returns the attribute string of an property.

Here you can find some more concrete hints and examples.

As a side note, the following statement:

Since property named "age" would always have a selector named "age" as well

is not correct, since a property can have custom getter and/or setter:

@property (nonatomic, getter=isImmediate) BOOL immediate;

EDIT:

Some sample code I found in another S.O. post:

const char * type = property_getAttributes(class_getProperty([self class], "myPropertyName"));
NSString * typeString = [NSString stringWithUTF8String:type];
NSArray * attributes = [typeString components separatedByString:@","];
NSString * typeAttribute = [attributes objectAtIndex:0];
NSString * propertyType = [typeAttribute substringFromIndex:1];
const char * rawPropertyType = [propertyType UTF8String];

if (strcmp(rawPropertyType, @encode(float)) == 0) {
 //it's a float
} else if (strcmp(rawPropertyType, @encode(int)) == 0) {
 //it's an int
} else if (strcmp(rawPropertyType, @encode(id)) == 0) {
 //it's some sort of object
} else ....
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top