Objective-C - Цитирование через все свойства класса? - программирование
Подтвердить что ты не робот

Objective-C - Цитирование через все свойства класса?

Есть ли способ перебрать все свойства объекта и получить их "имя" и "значение".

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

Возможно ли это?

4b9b3361

Ответ 1

Этот код можно использовать для перечисления всех свойств, объявленных в классе, и всех атрибутов свойств. Думаю, вас больше интересует разбор атрибута типа. Они подробно описаны здесь.

unsigned int numOfProperties;
objc_property_t *properties = class_copyPropertyList([self class], &numOfProperties);
for ( unsigned int pi = 0; pi < numOfProperties; pi++ ) {
    // Examine the property attributes
    unsigned int numOfAttributes;
    objc_property_attribute_t *propertyAttributes = property_copyAttributeList(properties[pi], &numOfAttributes);
    for ( unsigned int ai = 0; ai < numOfAttributes; ai++ ) {
        switch (propertyAttributes[ai].name[0]) {
            case 'T': // type
                break;
            case 'R': // readonly
                break;
            case 'C': // copy 
                break;
            case '&': // retain
                break;
            case 'N': // nonatomic 
                break;
            case 'G': // custom getter
                break;
            case 'S': // custom setter
                break;
            case 'D': // dynamic 
                break;
            default: 
                break;
        }
    }
    free(propertyAttributes);
}
free(properties);

Ответ 2

Я использую следующую категорию на NSObject, чтобы сказать, например, NSLog(@"%@", [someObject propertiesPlease]);, что приводит к записи в журнале, например...

someObject: {
    color = "NSCalibratedRGBColorSpace 0 0 1 1";
    crayon = Blueberry;
}

NSObject+Additions.h

@interface NSObject (Additions)
- (NSDictionary *)propertiesPlease;
@end

NSObject+Additions.m

@implementation NSObject (Additions)
- (NSDictionary *)propertiesPlease {
NSMutableDictionary *props = [NSMutableDictionary dictionary];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for (i = 0; i < outCount; i++) {
   objc_property_t property = properties[i];
   NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property)];
   id propertyValue = [self valueForKey:(NSString *)propertyName];
   if (propertyValue) [props setObject:propertyValue forKey:propertyName];
}
   free(properties);
   return props;
}
@end

Ответ 3

Возможно, class_copyPropertyList() сделает то, что вам нужно, но заметьте, что он возвращает декларируемые свойства.

Не все свойства объявлены - NSDictionary и NSMutableDictionary являются примерами классов, в которых вы можете установить свойства, которые не объявлены в классе.

Подробнее в docs.

Ответ 4

У меня еще нет привилегий комментариев, но для добавления в ответ @Costique есть дополнительный атрибут. Значение типа "V", которое является именем IVar, к которому может быть привязано свойство (через синтез). Это можно легко обнаружить с помощью этого

@interface Redacted: NSObject

@property (atomic, readonly) int foo;

@end


@implementation Redacted

@synthesize foo = fooBar;

@end

// for all properties
unsigned propertyCount = 0;
objc_property_t *properties = class_copyPropertyList([object class], &propertyCount);
for (int prop = 0; prop < propertyCount; prop++)
{
    // for all property attributes
    unsigned int attributeCount = 0;
    objc_property_attribute_t* attributes = property_copyAttributeList(property, &attributeCount);
    for (unsigned int  attr = 0; attr < attributeCount; attr++)
    {
        NSLog(@"Attribute %d: name: %s, value: %s", attr, attributes[attr].name, attributes[attr].value);
    }
}

2013-07-08 13: 47: 16.600 Redacted5162: 303] Атрибут 0: имя: T, значение: i

2013-07-08 13: 47: 16.601 Redacted [5162: 303] Атрибут 1: имя: R, значение:

2013-07-08 13: 47: 16.602 Redacted [5162: 303] Атрибут 2: имя: V, значение: fooBar