dchohfi / KeyValueObjectMapping

Automatic KeyValue Object Mapping for Objective-C, parse JSON/plist/Dictionary automatically
http://dchohfi.com/
MIT License
602 stars 90 forks source link

Crash on iOS 8 beta 5 if JSON returns a field named "description" #57

Open tomasebrennan opened 9 years ago

tomasebrennan commented 9 years ago

As part of Apple's big refactor job in iOS 8 one of the things they've changed is to turn the -description method in the NSObject protocol into a read only property.

If we have some JSON that returns a field named "description" the library will throw an exception (full stack trace below). This is because it's trying to set the readonly description property on NSObject.

Now I don't think this is really an issue with the KeyValueObjectMapping code itself. Its just that now "description" should be treated as a restricted keyword like "id" and it should be handled by developers with a custom DCObjectMapping map key path.

That being said, it's probably important to make people aware of this. "description" is a far more likely JSON field name than "id" or "alloc" or any other reserved keyword. Maybe you could throw your own exception which could contain a more helpful description than Apple's.

Full Stack Trace:

2014-08-05 16:29:59.327 My_App[64137:321932] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MyDataModel 0x7f1f7920> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key description.' * First throw call stack: ( 0 CoreFoundation 0x049a5df6 __exceptionPreprocess + 182 1 libobjc.A.dylib 0x04648837 objc_exception_throw + 44 2 CoreFoundation 0x049a5a11 -[NSException raise] + 17 3 Foundation 0x022e1c9e -[NSObject(NSKeyValueCoding) setValue:forUndefinedKey:] + 282 4 Foundation 0x0223dce8 _NSSetUsingKeyValueSetter + 115 5 Foundation 0x0223dc6d -[NSObject(NSKeyValueCoding) setValue:forKey:] + 267 6 My_App 0x005c3858 +[DCAttributeSetter assingValue:forAttributeName:andAttributeClass:onObject:] + 345 7 My_App 0x005c138f -[DCKeyValueObjectMapping parseValue:forObject:inAttribute:dictionary:] + 374 8 My_App 0x005c0c30 -[DCKeyValueObjectMapping setValuesOnObject:withDictionary:] + 615 9 My_App 0x005c09a6 -[DCKeyValueObjectMapping parseDictionary:forParentObject:] + 221 10 My_App 0x005c08c4 -[DCKeyValueObjectMapping parseDictionary:] + 48 11 My_App 0x0080eba5 - * My_App_Code * + 805 )

dchohfi commented 9 years ago

Try to override the key name to something diff using this class https://github.com/dchohfi/KeyValueObjectMapping/blob/master/KeyValueObjectMapping/DCObjectMapping.h

tomasebrennan commented 9 years ago

I already am. You can close the issue, I mainly just wanted to make others aware of the problem.

aokizen commented 9 years ago

JSON will return this field. But my object doesn't need the property that named "descriprion" , so I don't want to override the key name.

I override the method - (NSString *) findPropertyDetailsForKey: (NSString *)key onClass: (Class)class in DCPropertyFinder like this:

- (NSString *) findPropertyDetailsForKey: (NSString *)key onClass: (Class)class{
    objc_property_t property = class_getProperty(class, [key UTF8String]);
    if (property) {
        NSString *attributeDetails = [NSString stringWithUTF8String:property_getAttributes(property)];

        NSString *objectAttribute;
        objc_property_t objectProperty = class_getProperty([NSObject class], [key UTF8String]);
        if (objectProperty) {
            objectAttribute = [NSString stringWithUTF8String:property_getAttributes(objectProperty)];
        }
        if (objectAttribute == nil || (objectAttribute && ![attributeDetails isEqualToString:objectAttribute])) {
            return attributeDetails;
        }
    }
    return nil;
}

I can add the keyValueMapping mannually if I really need these properties.

ShadyElyaski commented 9 years ago

Try adding @synthesize description; in your .m file