Objective-C中的类属性列表

ani*_*hin 29 class object objective-c ios

有没有办法获得某种类的属性数组?例如,如果我有这样的界面

@interface MyClass : NSObject
    @property (strong,nonatomic) UILabel *firstLabel;
    @property (strong,nonatomic) UILabel *secondLabel;        
@end
Run Code Online (Sandbox Code Playgroud)

我可以在不知道名字的情况下获得实施中的标签参考吗?

@implementation MyClass
    -(NSArray*)getListOfAllLabels
    {
            ?????
    }        
@end
Run Code Online (Sandbox Code Playgroud)

我知道我可以轻松地完成它[NSArray arrayWithObjects:firstLabel,secondLabel,nil],但我想用某种类枚举来做for (UILabel* oneLabel in ???[self objects]???)

小智 77

更确切地说,如果我正确地得到它,你需要动态的,运行时观察属性.做这样的事情(在self上实现这个方法,你要反省的类):

#import <objc/runtime.h>

- (NSArray *)allPropertyNames
{
    unsigned count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);

    NSMutableArray *rv = [NSMutableArray array];

    unsigned i;
    for (i = 0; i < count; i++)
    {
        objc_property_t property = properties[i];
        NSString *name = [NSString stringWithUTF8String:property_getName(property)];
        [rv addObject:name];
    }

    free(properties);

    return rv;
}

- (void *)pointerOfIvarForPropertyNamed:(NSString *)name
{
    objc_property_t property = class_getProperty([self class], [name UTF8String]);

    const char *attr = property_getAttributes(property);
    const char *ivarName = strchr(attr, 'V') + 1;

    Ivar ivar = object_getInstanceVariable(self, ivarName, NULL);

    return (char *)self + ivar_getOffset(ivar);
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

SomeType myProperty;
NSArray *properties = [self allPropertyNames];
NSString *firstPropertyName = [properties objectAtIndex:0];
void *propertyIvarAddress = [self getPointerOfIvarForPropertyNamed:firstPropertyName];
myProperty = *(SomeType *)propertyIvarAddress;

// Simpler alternative using KVC:
myProperty = [self valueForKey:firstPropertyName];
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 一旦你有了字符串,就可以更容易地使用KVC并使用`[self valueForKey:propertyName];`.使用存取器通常比直接使用背面ivar更好 - 所以你可以利用统一的访问原则,并给你自己一些钩子,以便在以后挂帽. (2认同)
  • 不要用`get`前缀命名方法; 仅限于一个非常具体的用例,这不是它. (2认同)

小智 12

使用NSObject的attributeKeys方法.

    for (NSString *key in [self attributeKeys]) {

        id attribute = [self valueForKey:key];

        if([attribute isKindOfClass:[UILabel  class]])
        {
         //put attribute to your array
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 这看起来像是最优雅的解决方案但遗憾的是方法属性Keys仅适用于Mac OS X,而不适用于iOS ... (14认同)

msk*_*msk 8

看看这个链接.它是客观C运行时的客观c包装器.

您可以使用以下代码

uint count;
objc_property_t* properties = class_copyPropertyList(self.class, &count);
    NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        const char* propertyName = property_getName(properties[i]);
        [propertyArray addObject:[NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
    }
    free(properties);
Run Code Online (Sandbox Code Playgroud)


Vla*_*lad 6

您必须包含运行时标头

 #import<objc/runtime.h>
uint propertiesCount;
objc_property_t *classPropertiesArray = class_copyPropertyList([self class], &propertiesCount);
free(classPropertiesArray);
Run Code Online (Sandbox Code Playgroud)