【问题标题】:How could I check for a particular property at runtime, along with its return type?如何在运行时检查特定属性及其返回类型?
【发布时间】:2013-01-14 21:10:13
【问题描述】:

由于名为“age”的属性也总是有一个名为“age”的选择器,我可以使用respondsToSelector 作为question suggests,它会告诉我在运行时是否存在特定的选择器在任何给定的对象中。

如果存在名为“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;
}

【问题讨论】:

  • 我认为你需要添加 if (properties) free(properties);到你得心应手的类别实用方法
  • 可能是对的。几个月来我没有做过任何 Objective-C 编码,感觉很生疏。我也不是 100% 确定你是对的。 :-) 我可能需要一些 Objective-C 运行时阅读才能弄清楚。
  • 在做同样的事情之前,我已经编写了自己的类别,并且还必须自己解决这个问题。只是在看到 Carl 的回答提到 free() 使用 property_copyAttributeValue 之后才注意到它现在更仔细地查看文档
  • 好的,我相信你的话。请您进行代码编辑(编辑我的帖子),如果您的代表太低,我会批准它
  • 感谢您的编辑,DonnaLea!

标签: objective-c introspection dynamic-typing


【解决方案1】:

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

class_copyPropertyList

描述类声明的属性。

然后property_getAttributes:

property_getAttributes

返回属性的属性字符串。

Here你可以找到一些更具体的提示和例子。

作为旁注,以下声明:

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

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

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

编辑:

我在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 ....

【讨论】:

  • 我认为属性“abc”必须具有读取选择器“abc”是“合同”的一部分。不是吗?
  • 您可以覆盖该“合同”并指定您想要的名称。看例子。我不认为在这种情况下,您还会在 isImmediate 旁边有一个 immediate 选择器。
  • 所以 property_getAttributes 会返回很多内容为 (char*),有没有直接的方法来检查“type : BOOL”?
  • 我不这么认为,但我发现了一些示例代码可能会有所帮助...检查我的编辑。
  • 从那个链接的问题看来,运行时装箱可能比用蛮力这样做更惯用:stackoverflow.com/questions/3497625/…
【解决方案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] 数字属性类型 属性 = i

假设MyClass 看起来像:

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

@implementation MyClass
@end

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

【讨论】:

  • property_copyAttributeValue(x,"T") 正是我想要的。
  • 我在我的问题中将其写为实用程序类别,以及free(attribute)
  • @WarrenP 太棒了!要记住的一件事是,您在问题中暗示了这一点,即检查该属性的实际实现。您可以通过分别检查“G”和“S”属性类型来检查是否使用了自定义 getter 或 setter。并且可能需要特别注意动态属性(类型“D”返回一个空字符串,而不是NULL) - 我不完全确定如何验证它们是否有实现,我想检查选择器很好但是我不知道这将如何与主要使用 KVC 作为其属性的 NSManagedObject 子类一起使用。
  • 我认为实际上在运行时 INVOKING 这样的东西,KVC 是要走的路。我只是要在运行时使用它来检查“签名”,“这是一个具有返回字符串的名称属性的对象吗?”是的?然后它是我的目的的“命名对象”。如果我想看东西,我会完全依赖KVC。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 2011-02-21
  • 1970-01-01
相关资源
最近更新 更多