所有子类的class_copyPropertyList也是

时间:2014-08-29 16:48:29

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

这是解释
List of class properties in Objective-C
如何使用class_copyPropertyList在运行时获取类的所有属性。

我测试了这个并且工作正常。
我注意到它只会从该类获取属性,而不是它的子类。

CODE:

@interface JustForThisUT : NSObject
@property NSUInteger public_access;
@end

@interface JustForThisUT ()
@property NSUInteger private_access;
@end

@implementation JustForThisUT
@end



@interface JustForThisUTParent : JustForThisUT
@property NSUInteger my_public_access;
@end

@interface JustForThisUTParent ()
@property NSUInteger my_private_access;
@end

@implementation JustForThisUTParent
@end

如果我在JustForThisUT上使用它,我将获得2个属性(public_access& private_access)
如果我在JustForThisUTParent上使用它,我将获得2个属性(my_public_access& my_private_access)

但是对于JustForThisUTParent我期望从JustForThisUT获得4,从JustForThisUTParent获得2。

我的问题是
如何从当前类和所有子类获取属性?
它甚至可能吗?

2 个答案:

答案 0 :(得分:4)

您必须先找到所有子类,然后使用class_copyPropertyList()列出每个类的属性,并根据需要进行单独处理。

然而,这有一个糟糕的代码味道。这种动态,反射沉重的编程水平与ObjC的真正设计背道而驰。您最终会得到一个难以维护的脆弱代码库。

如果你真的想要这种性质的动态,那么在每个类上实现一个类方法,它返回你想要能够动态访问的属性名列表。

答案 1 :(得分:0)

找到所有超类相当简单(我认为这是你的意思,而不是子类);你只需循环直到class.superclass == NSObject.class。

请注意@bbum关于这是一个糟糕的代码味道的评论。阅读他的答案并考虑其他方法,并真正考虑为什么要这样做,以及是否有更好的方法。

也就是说,这是一个完整的代码示例,它从类中检索所有BOOL属性。将其扩展到其他属性类型会很容易 - 请参阅链接的问题。

/**
 * Get a name for an Objective C property
 *
 */
- (NSString *)propertyTypeStringOfProperty:(objc_property_t) property {
    NSString *attributes = @(property_getAttributes(property));

    if ([attributes characterAtIndex:0] != 'T')
        return nil;

    switch ([attributes characterAtIndex:1])
    {
        case 'B':
            return @"BOOL";
    }

    assert(!"Unimplemented attribute type");
    return nil;
}

/**
 * Get a name->type mapping for an Objective C class
 *
 * Loosely based on http://stackoverflow.com/questions/754824/get-an-object-properties-list-in-objective-c
 *
 * See 'Objective-C Runtime Programming Guide', 'Declared Properties' and
 * 'Type Encodings':
 *   https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101
 *   https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-SW1
 *
 * @returns (NSString) Dictionary of property name --> type
 */

- (NSDictionary *)propertyTypeDictionaryOfClass:(Class)klass {
    NSMutableDictionary *propertyMap = [NSMutableDictionary dictionary];
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(klass, &outCount);
    for(i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        const char *propName = property_getName(property);
        if(propName)
        {
            propertyMap[@(propName)] = [self propertyTypeStringOfProperty:property];
        }
    }
    free(properties);
    return propertyMap;
}

- (NSDictionary *)settingsProperties
{
    if (!_settingsProperties)
    {
        Class class = _settings.class;
        NSMutableDictionary *propertyMap = [[NSMutableDictionary alloc] init];

        do
        {
            [propertyMap addEntriesFromDictionary:[self propertyTypeDictionaryOfClass:class]];
        }
        while ((class = class.superclass) != NSObject.class);

        _settingsProperties = propertyMap;
    }

    return _settingsProperties;
}