在iOS中检索类的属性列表

时间:2014-07-21 19:24:06

标签: objective-c ios8 nsobject objective-c-runtime

我正在尝试检索我的类或其任何子类定义的所有属性的列表。以下代码片段是我一直使用的代码,它一直正常工作,直到最近的iOS8 beta 4。

if(!dictionary) {
    dictionary = [NSMutableDictionary dictionary];

    // Get all properties we have until we hit CBLNestedModel
    while(klass != [CBLNestedModel class]) {
        unsigned count;
        objc_property_t* properties = class_copyPropertyList(klass, &count);
        for (unsigned i = 0; i < count; i++) {
            objc_property_t property = properties[i];

            const char* propertyNameC = property_getName(property);
            NSString* propertyName = [NSString stringWithUTF8String:propertyNameC];
            const char* propertyAttrC = property_getAttributes(property);
            NSString* propertyAttrS = [NSString stringWithUTF8String:propertyAttrC];
            NSArray* propertyAttr = [propertyAttrS componentsSeparatedByString:@","];
            NSLog(@"%@ has property %@", NSStringFromClass(klass), propertyName);

            dictionary[propertyName] = propertyAttr;
        }
        free(properties);
        klass = [klass superclass];
    }

    propertyDictionary[klassString] = dictionary;
}

CBLNestedModel派生自NSObject。基本上,我想要CBLNestedModel的任何子类声明的所有属性,或者它的子类。我面临的问题是,现在,这段代码返回了我的子类中未定义的无关属性。对于某些类,propertyNames返回@"superclass", @"description", @"debugDescription", @"hash",即使我从未定义过这些属性在我的子类中的任何地方。

奇怪的是,对于CBLNestedModel的所有子类,不会返回这些无关的属性,但仅针对某些子类。但是,在我的应用程序的每次运行中,它们都将可靠地返回给那些子类。

现在知道为什么会这样吗?

2 个答案:

答案 0 :(得分:9)

您的CBLNestedModel子类是否遵守任何协议?我之前看到过与我所拥有的对象类似的问题,无法弄清楚为什么hashdescriptionsuperclassdebugDescription出现了,我终于想到了出。这就是我所拥有的:

@interface FOOObject : NSObject<NSCopying, FOOOtherProtocol>

看起来很好,它是NSObject的直接子类。事实上,我有其他对象来测试它,一个具有属性,一个没有。

@interface FOOObjectWithProperties : NSObject

@property NSString *someProperty;

@end

@interface FOOObjectWithoutProperties : NSObject
@end

在测试FOOObjectWithPropertiesFOOObjectWithoutProperties期间,都包含上述四个NSObject属性,但原始FOOObject DID

那有什么区别?好好看NSCopying它似乎没有添加任何属性,所以我查看了FOOOtherProtocol,我已经实现了一些协议,并且它没有声明任何属性。

<强>无论其

查看FOOOtherProtocol的声明:

@protocol FOOOtherProtocol<NSObject>

。 objective-c运行时的东西 NOT 在返回的内容中包含超类属性,但它包括在协议扩展中声明的属性(强制遵守其他协议的协议)。

注意hashdescriptionsuperclassdebugDescription的所有内容?

查看NSObject protocol declaration

中声明的位置

从子类的协议中删除强制NSObject协议遵从性(因为它们是NSObject的子类,无论如何已经遵守它),你应该看到这些属性消失了。

答案 1 :(得分:1)

在iOS 8上看起来,这4个方法现在在NSObject中被声明为只读属性。

More info here