2012-02-13 18 views
9

Quiero crear una clase base Objective-C que realiza una operación en todas las propiedades (de diferentes tipos) en tiempo de ejecución. Dado que los nombres y tipos de las propiedades no siempre se conocerán, ¿cómo puedo hacer algo como esto?Loop a través de todas las propiedades de objeto en tiempo de ejecución

@implementation SomeBaseClass 

- (NSString *)checkAllProperties 
{ 
    for (property in properties) { 
     // Perform a check on the property 
    } 
} 

EDIT: Esto sería particularmente útil en una - (NSString *)description: override personalizado.

Respuesta

21

Para ampliar la respuesta MVDS' (empecé a escribir esto antes de que vi de él), aquí hay un pequeño programa de ejemplo que utiliza la API de tiempo de ejecución de Objective-C para recorrer e imprimir información sobre cada propiedad en una clase:

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

@interface TestClass : NSObject 

@property (nonatomic, retain) NSString *firstName; 
@property (nonatomic, retain) NSString *lastName; 
@property (nonatomic) NSInteger *age; 

@end 

@implementation TestClass 

@synthesize firstName; 
@synthesize lastName; 
@synthesize age; 

@end 

int main(int argc, char *argv[]) { 
    @autoreleasepool { 
     unsigned int numberOfProperties = 0; 
     objc_property_t *propertyArray = class_copyPropertyList([TestClass class], &numberOfProperties); 

     for (NSUInteger i = 0; i < numberOfProperties; i++) 
     { 
      objc_property_t property = propertyArray[i]; 
      NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)]; 
      NSString *attributesString = [[NSString alloc] initWithUTF8String:property_getAttributes(property)]; 
      NSLog(@"Property %@ attributes: %@", name, attributesString); 
     } 
     free(propertyArray); 
    } 
} 

salida: atributos

edad del inmueble: T^q, Vage
Propiedad lastName atributos: T @ "NSString", &, N, VlastName
propiedad NOMBRE atributos: T @ "NSString", &, N, VfirstName

Tenga en cuenta que este programa debe ser compilado con ARC encendido.

+0

Una buena pregunta de seguimiento sería cómo devolver los valores de cada uno dinámicamente ... Estoy pensando crear dinámicamente un descriptor de acceso, pero sintácticamente, todavía estoy tratando de resolverlo. –

+1

Hay varias formas de hacerlo, pero la más directa sería usar KVC: 'id value = [self valueForKey: @" propertyName "]'. Se vuelve un poco más complicado donde tiene los tipos de retorno primitivo (int, float, etc) y de objeto (NSString, etc.), pero la premisa básica funcionará. –

+0

este código se filtra como el infierno – mvds

14

Uso

objc_property_t * class_copyPropertyList(Class cls, unsigned int *outCount) 

y leer https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html sobre cómo hacer esto con exactitud.

Parte del código para que te va:

#import <objc/runtime.h> 

unsigned int count=0; 
objc_property_t *props = class_copyPropertyList([self class],&count); 
for (int i=0;i<count;i++) 
{ 
    const char *name = property_getName(props[i]); 
    NSLog(@"property %d: %s",i,name); 
} 
+1

Stellar. Recurso perfecto para la locura del tiempo de ejecución más cercano al metal. –

+0

Muchas gracias, funciona bien, ¿cómo copio las propiedades de un objeto a otro en tiempo de ejecución? –

+1

@PavanSaberjack usando 'valueForKey:' y 'setValue: forKey:', donde hay que tomar nota de que 'char * name' no puede ser utilizado como objeto (es decir, como' NSString') sin ningún tipo de conversión. – mvds

Cuestiones relacionadas