Lista de propiedades de clase en Objective-C

¿Hay alguna forma de obtener una variedad de propiedades de clase de cierto tipo? Por ejemplo, si tengo una interfaz como esta

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

¿Puedo obtener la referencia de esas tags en la implementación sin saber su nombre?

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

Sé que puedo hacerlo fácilmente con [NSArray arrayWithObjects:firstLabel,secondLabel,nil] , pero me gustaría hacerlo con algún tipo de enumeración de clases como for (UILabel* oneLabel in ???[self objects]???)

Entonces, para ser más precisos, quieres una observación dinámica, en tiempo de ejecución de las propiedades, si lo obtuve correctamente. Haga algo como esto (implemente este método en sí mismo, la clase que desea introspectar):

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

Úselo así:

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

Espero que esto ayude.

use el método attributeKeys de NSObject.

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

Mira este enlace . Es un contenedor objective c sobre el tiempo de ejecución del objective C.

Puedes usar código como a continuación

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

Debe incluir los encabezados de tiempo de ejecución

  #import uint propertiesCount; objc_property_t *classPropertiesArray = class_copyPropertyList([self class], &propertiesCount); free(classPropertiesArray); 

La respuesta de @ user529758 no funcionará con ARC y no mostrará las propiedades de ninguna clase antecesora.

Para solucionar esto, debe recorrer la jerarquía de clases y usar el [NSObject valueForKey:] compatible con ARC para obtener los valores de las propiedades.

Person.h:

 #import  extern NSMutableArray *propertyNamesOfClass(Class klass); @interface Person : NSObject @property (nonatomic) NSString *name; @end 

Person.m:

 #import "Person.h" #import  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]; } 

Estudiante.h:

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

Student.m:

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

main.m:

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

La solución de serhats es genial. Desafortunadamente no funciona para iOS (como mencionaste) (y esta pregunta está etiquetada para iOS). Una solución sería obtener una representación NSDictionary del objeto y luego acceder a ella normalmente como pares clave-valor. Yo recomendaría una categoría para NSObject:

Archivo de cabecera:

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

Archivo de Implementación:

 #import "NSObject+NSDictionaryRepresentation.h" #import  @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 

Tomado de este artículo: http://hesh.am/2013/01/transform-properties-of-an-nsobject-into-an-nsdictionary/

De esta forma, podrías hacer algo similar a los mencionados por los serhats:

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