I am trying to deep-parse my own collection of objects into an NSDictionary (for JSON).
I have a base object class, which All of my models extend, and this baseobject in turn extends NSObject:
@interface BaseObj : NSObject <DICTMaker>
- (NSMutableDictionary *) toDICT;
@end
In the method, I use objc-runtime to get a list of properties. Any property which I can get a reference to using [self valueForKey:], I go ahead and insert into my dictionary the name and value of the property.
However, what I’ve noticed thus far is that NSNumbers and user defined classes are not added to the dictionary! My parser most assuredly identifies them, because I have it spitting out everything to the log; but [self valueForKey:] returns nil on all NSNumbers and user defined objects.
- (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;
}
Here is a sample object I threw at the creator:
@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];
The resulting dictionary only contained entries for email, password, and 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":"my@email.com"}}
Any assistance please =} !
Maybe I understood the problem wrong, but are your referral, primary and so not simply null?
If they are not in the keyvalue store, you would get an exception.
You else part is only called, if the property is found in the keyvalue store but has a nil assigned. At least from your example code, one cannot decide, if the values are set.
If I reduce your example to the code below, I get the following output
test with Value: (null)
Unable to get ref to: test
aNumber with Value: 5
test is null and will give your message “unable…”. aNumber is correct. If I change test to some text, the “unable…” part vanishes. The additional member variable _noProp which is not a property does not occur here, as copyPropertyList copies only properties.