如何动态确定Objective-C属性类型?

时间:2012-03-09 18:37:29

标签: objective-c ios properties objective-c-runtime

我正在尝试动态确定Objective-C中属性的类型。根据我在本网站和其他地方的内容,我相信我做的是正确的。但是,我的代码无效。

下面的代码段演示了这个问题。尝试获取“backgroundColor”和“frame”的属性信息(两者都是UIView的有效属性)失败(class_getProperty()返回NULL):

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

按照描述here枚举属性也不会产生预期的结果。以下代码:

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

生成此输出:

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

缺少记录的属性,例如“backgroundColor”,“frame”等,而包括“caretRect”和“gesturesEnabled”等未记录的属性。

非常感谢任何帮助。如果它是相关的,我在iOS模拟器上看到这种行为。我不知道在实际设备上是否会发生同样的事情。

谢谢, 格雷格

3 个答案:

答案 0 :(得分:6)

您正在获取UIView属性,问题是backgroundColor不是UIView属性,是类别属性。检查UIView.h。我想你不能得到一个objc_category,但看看class-dump。

答案 1 :(得分:0)

稍微躲避这个问题,以下工作:

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

因此,运行时可能会以某种方式失去backgroundColor属性的事实,但您似乎始终在第一个代码片段中以该信息开头,因此它只检查getter的返回类型。

答案 2 :(得分:0)

您可以找到类别属性作为方法。

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

然后你检查一下......

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

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

不要忘记尊重BOOL属性的getter / setter表示法,搜索'isHidden'而不是'hidden'。