2012-02-13 2 views
9

Я хочу создать базовый класс Objective-C, который выполняет операцию во всех свойствах (разных типов) во время выполнения. Поскольку имена и типы свойств не всегда будут известны, как я могу сделать что-то подобное?Петля через все свойства объекта во время выполнения

@implementation SomeBaseClass 

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

EDIT: Это будет особенно полезно в пользовательской - (NSString *)description: переопределения.

ответ

21

Чтобы расширить ответ MVDS' (начал писать это, прежде чем я увидел его), вот небольшая выборка программа, которая использует Objective-C во время выполнения API Переберите и печатать информацию о каждой собственности в классе:

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

Выход:

возраст недвижимости атрибуты: T^д, VAGE
Свойство LastName атрибуты: T @ "NSString", &, N, VlastName
Свойство ПгвЬЫате атрибуты: T @ "NSString", &, N, VfirstName

Заметьте, что эта программа должна быть составлена ​​с ARC включенный.

+0

Хороший вопрос о последующих действиях заключается в том, как динамически возвращать значения каждого из них ... Я думаю, что динамически создавать аксессуар, но синтаксически, я все еще пытаюсь понять это. –

+1

Есть несколько способов сделать это, но самым простым было бы использовать KVC: 'id value = [self valueForKey: @" propertyName "]'. Получается немного сложнее, если у вас есть как примитивные (int, float, и т. Д.), Так и объекты (NSString и т. Д.), Но основная посылка будет работать. –

+0

этот код просачивается как ад – mvds

14

Использование

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

и читать https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html о том, как сделать это точно.

Некоторый код, чтобы вы собираетесь:

#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

Звездный. Идеальный ресурс для безумства безубыточности по сравнению с металлом. –

+0

Большое спасибо, хорошо работает, как мне копировать объекты одного объекта во время выполнения? –

+1

@PavanSaberjack с использованием 'valueForKey:' и 'setValue: forKey:', где вы должны заметить, что 'char * name' не может использоваться как объект (т. Е. Как' NSString') без какой-либо формы преобразования. – mvds

Смежные вопросы