2

由于名为“age”的属性也总是有一个名为“age”的选择器,我可以respondsToSelector按照这个问题的建议使用它,这将告诉我在运行时是否存在任何给定对象中的特定选择器。

如果存在名为“age”的属性,我可以验证这一点。我怎么知道该选择器(该属性的读取方法)是返回对象(id)还是非对象(int)?

这种类型确定是否可以在运行时进行,还是 Objective-C 方法总是假设有人使用我希望它使用的类型实现了该方法,或者我也可以验证返回类型?

这是在 XCode 4.5 中使用最新的 Objective-C 版本(LLVM 4.1)。

更新:这是我想出的实用程序类别 NSObject:

   - (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;
}

在研究这个问题时,我还编写了这个方便实用的实用方法,可以列出该对象的所有属性:

- (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;
}
4

2 回答 2

3

您可以使用class_copyPropertyList来获取在类中声明的属性列表。

class_copyPropertyList

描述类声明的属性。

然后property_getAttributes

property_getAttributes

返回属性的属性字符串。

在这里,您可以找到一些更具体的提示和示例。

作为旁注,以下声明:

由于名为“age”的属性总是有一个名为“age”的选择器

不正确,因为属性可以具有自定义 getter 和/或 setter:

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

编辑:

我在另一个 SO 帖子中找到的一些示例代码:

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 ....
于 2013-01-14T21:21:06.543 回答
2

假设您已经知道属性名称,您可以采取的一种方法是使用该class_getProperty函数。您还可以使用该property_copyAttributeValue()函数按名称获取特定属性:

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);

将记录:

2013-01-14 14:45:37.382 RuntimeFun[61304:c07] number 属性类型属性 = i

假设MyClass看起来像:

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

@implementation MyClass
@end

一个你有你的类型属性字符串,然后你可以将它与各种Objective-C 类型编码进行比较。完成比较后,请务必调用free()您的属性字符串。

于 2013-01-14T22:01:53.310 回答