2012-06-11 2 views
1

Я пытаюсь глубоко проанализировать собственную коллекцию объектов в NSDictionary (для JSON).ObjC valueForKey не работает для NSNumber или UDT

У меня есть базовый класс объекта, который Все моих моделей расширения, и это BaseObject в свою очередь, расширяет NSObject:

@interface BaseObj : NSObject <DICTMaker> 
    - (NSMutableDictionary *) toDICT; 
@end 

В методе я использую ObjC-среды выполнения, чтобы получить список свойств. Любое свойство, которое я могу получить ссылку на использование [self valueForKey:], я иду вперед и вставляю в свой словарь имя и значение свойства.

Однако, я заметил, что NSNumber s и пользовательские классы не добавляются в словарь! Мой синтаксический анализатор, безусловно, идентифицирует их, потому что я все это выплевываю в журнал; но [self valueForKey:] возвращает nil по всем NSNumbers и объектам, определенным пользователем.

- (NSMutableDictionary *)toDICT { 
    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]; 

     // Both of these work, I promise: 
     NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)]; 
     NSString *propertyType = [NSString stringWithUTF8String:getPropertyType(property)]; 

     NSLog(@"%@ of Type: %@", propertyName, propertyType); 
     id propertyValue = [self valueForKey:propertyName]; 
     if ([ propertyValue respondsToSelector:@selector(toDICT:) ]) 
      [ props setObject:[propertyValue toDICT] forKey:propertyName ]; 
     else if (propertyValue) 
      [ props setObject:propertyValue forKey:propertyName ]; 
     else 
      NSLog(@"Unable to get ref to: %@", propertyName); 
    } 
    free(properties); 
    return props; 
} 

Вот пример объекта я бросил на создатель:

@interface UserRegistrationLocation : BaseObj { 
    NSString *address, *street, *street_2, *city; 
    NSNumber *addr_state, *addr_zip; 
} 

@interface UserRegistrationContact : BaseObj { 
    NSString *first_name, *last_name; 
    NSString *p_phone_area, *p_phone_first_3, *p_phone_last_4; 
    NSString *s_phone_area, *s_phone_first_3, *s_phone_last_4; 
} 

@interface UserRegistration : BaseObj { 
    NSString *email, *password, *password_confirm; 
    NSNumber *referral; 

    UserRegistrationContact *primary, *secondary; 
    UserRegistrationLocation *address; 
} 

NSMutableDictionary *mydict = [myUserRegistration toDICT]; 

Полученный словарь содержится только записи для электронной почты, пароль и password_confirm:

[11012:f803] Unable to get ref to: referral 
[11012:f803] Unable to get ref to: primary 
[11012:f803] Unable to get ref to: secondary 
[11012:f803] Unable to get ref to: address 
[11012:f803] {"user":{"password":"haxme123","password_confirm":"haxme123","email":"[email protected]"}} 

Любая помощь, пожалуйста = }!

ответ

1

Возможно, я понял проблему неправильно, но ваш реферал, первичный и так не просто нуль? Если они не находятся в хранилище ключей, вы получите исключение. Вы еще часть вызывается только в том случае, если свойство найдено в хранилище значений ключей, но имеет назначенный нуль. По крайней мере, из вашего примера кода нельзя решить, если значения установлены.

Если я уменьшить свой пример кода ниже, я получаю следующие выходные тест с Value: (нулевой) Не удалось получить реф к: тест aNumber с Value: 5

тест является недействительным и воля дайте вашему сообщению «неспособный ...». aNumber правильный. Если я изменил тест на какой-то текст, часть «неспособная ...» исчезнет. Дополнительная переменная-член_noProp, которая не является свойством, здесь не встречается, поскольку copyPropertyList копирует только свойства.

@interface TestValueForKey : NSObject { 
    NSString* _test; 
    NSString* _noProp; 
    NSNumber* _aNumber; 
} 

@property (retain) NSString* test; 
@property (retain) NSNumber* aNumber; 

-(void)myTest; 

@implementation TestValueForKey 

@synthesize test = _test; 
@synthesize aNumber = _aNumber; 

-(id)init 
{ 
    if((self = [super init]) != nil) { 
     _test = nil; 
     _aNumber = [NSNumber numberWithInt:5]; 
    } 

    return self; 
} 

-(void)myTest 
{ 
    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]; 

     // Both of these work, I promise: 
     NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)]; 

     id propertyValue = [self valueForKey:propertyName]; 
     NSLog(@"%@ with Value: %@", propertyName, propertyValue); 
     if (propertyValue) 
      [ props setObject:propertyValue forKey:propertyName ]; 
     else 
      NSLog(@"Unable to get ref to: %@", propertyName); 
    } 
    free(properties); 
} 
@end 
+0

Как смущающе, мои внутренние объекты были назначены данными ..но сами классы не были правильно инициализированы! -10programmer pnts –

2

Вы только объявили ivars для значений, а не свойств. class_copyPropertyList@property объявлений. Вы можете использовать функции доступа ivar, такие как class_getInstanceVariable.

Однако, я думаю, что этот подход пытается быть слишком умным. Я бы выполнил метод, который возвращает массив ключей для сериализации, например, -(NSArray *)keysForJSONSerialization. Это выявило бы намерение более четко и позволит вам предотвратить сериализацию определенных свойств (которые, как я подозреваю, вы захотите в какой-то момент).

+0

Я предположил, что объявления свойств просто не были показаны - так как имена появляются в журналах, они должны существовать в массиве? +1 для второго абзаца, хотя – jrturton

+0

Как предлагалось jrtuton, на самом деле присутствовали соответствующие объявления '@ property' и' @ synhesize', хотя они были удалены из приведенного выше списка для упрощения. Но все равно никаких денег –