Objective-C中的类属性列表

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

@interface MyClass : NSObject @property (strong,nonatomic) UILabel *firstLabel; @property (strong,nonatomic) UILabel *secondLabel; @end 

我可以在不知道名字的情况下获得对这些标签的引用吗?

 @implementation MyClass -(NSArray*)getListOfAllLabels { ????? } @end 

我知道我可以用[NSArray arrayWithObjects:firstLabel,secondLabel,nil]轻松地做到这一点,但我想用某种类的枚举类似于for (UILabel* oneLabel in ???[self objects]???)

所以更准确地说,如果我正确地得到了它,就需要dynamic的,运行时的属性观察 。 做这样的事情(在自我实现这个方法,你想要反思的类):

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

像这样使用它:

 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]; 

希望这可以帮助。

使用NSObject的attributeKeys方法。

  for (NSString *key in [self attributeKeys]) { id attribute = [self valueForKey:key]; if([attribute isKindOfClass:[UILabel class]]) { //put attribute to your array } } 

看看这个链接 。 这是一个客观的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); 

您必须包含运行时头文件

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

@ user529758的答案将不适用于ARC,它不会列出任何祖先类的属性。

为了解决这个问题,你需要遍历类层次结构,并使用ARC兼容的[NSObject valueForKey:]来获取属性值。

Person.h:

 #import <Foundation/Foundation.h> extern NSMutableArray *propertyNamesOfClass(Class klass); @interface Person : NSObject @property (nonatomic) NSString *name; @end 

Person.m:

 #import "Person.h" #import <objc/runtime.h> NSMutableArray *propertyNamesOfClass(Class klass) { unsigned int count; objc_property_t *properties = class_copyPropertyList(klass, &count); NSMutableArray *rv = [NSMutableArray array]; for (unsigned int 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; } @implementation Person - (NSMutableArray *)allPropertyNames { NSMutableArray *classes = [NSMutableArray array]; Class currentClass = [self class]; while (currentClass != nil && currentClass != [NSObject class]) { [classes addObject:currentClass]; currentClass = class_getSuperclass(currentClass); } NSMutableArray *names = [NSMutableArray array]; [classes enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(Class currentClass, NSUInteger idx, BOOL *stop) { [names addObjectsFromArray:propertyNamesOfClass(currentClass)]; }]; return names; } - (NSString*)description { NSMutableArray *keys = [self allPropertyNames]; NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:keys.count]; [keys enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) { properties[key] = [self valueForKey:key]; }]; NSString *className = NSStringFromClass([self class]); return [NSString stringWithFormat:@"%@ : %@", className, properties]; } 

Student.h:

 #import "Person.h" @interface Student : Person @property (nonatomic) NSString *studentID; @end 

Student.m:

 #import "Student.h" @implementation Student @end 

main.m文件:

 #import <Foundation/Foundation.h> #import "Student.h" int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... Student *student = [[Student alloc] init]; student.name = @"John Doe"; student.studentID = @"123456789"; NSLog(@"student - %@", student); } return 0; } 

serhats的解决scheme非常不幸,它不适用于iOS(正如你所提到的)(这个问题被标记为iOS)。 解决方法是获取对象的NSDictionary表示,然后以键值对的forms正常访问它。 我会推荐一个NSObject类别:

页眉文件:

 @interface NSObject (NSDictionaryRepresentation) /** Returns an NSDictionary containing the properties of an object that are not nil. */ - (NSDictionary *)dictionaryRepresentation; @end 

实现的文件:

 #import "NSObject+NSDictionaryRepresentation.h" #import <objc/runtime.h> @implementation NSObject (NSDictionaryRepresentation) - (NSDictionary *)dictionaryRepresentation { unsigned int count = 0; // Get a list of all properties in the class. objc_property_t *properties = class_copyPropertyList([self class], &count); NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:count]; for (int i = 0; i < count; i++) { NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])]; NSString *value = [self valueForKey:key]; // Only add to the NSDictionary if it's not nil. if (value) [dictionary setObject:value forKey:key]; } free(properties); return dictionary; } @end 

从这篇文章借用: http : //hesh.am/2013/01/transform-properties-of-an-nsobject-into-an-nsdictionary/

这样,你可以做一些类似的服务提到:

 for (NSString *key in objectDic.allKeys) { if([objectDic[key] isKindOfClass:[UILabel class]]) { //put attribute to your array } }