From a3074e98b2dc3414a32129debfc909daeba3f8d1 Mon Sep 17 00:00:00 2001 From: Saul Mora Date: Mon, 28 Nov 2011 19:32:17 -0700 Subject: [PATCH] Swizzle valueForUndefinedKey: method with MR_valueForUndefinedKey: on the object being imported to support data importing for undefined keys (ie. data wasn't included) without crashing (default behaivior) --- .../DataImport/NSObject+MagicalDataImport.m | 4 +- .../NSManagedObject+MagicalDataImport.m | 47 +++++++++++++++---- Source/MagicalRecordHelpers.m | 2 + 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/Source/Categories/DataImport/NSObject+MagicalDataImport.m b/Source/Categories/DataImport/NSObject+MagicalDataImport.m index 8323b0e..1afb069 100644 --- a/Source/Categories/DataImport/NSObject+MagicalDataImport.m +++ b/Source/Categories/DataImport/NSObject+MagicalDataImport.m @@ -13,12 +13,12 @@ NSUInteger const kMagicalRecordImportMaximumAttributeFailoverDepth = 10; @implementation NSObject (MagicalRecord_DataImport) -#warning If you implement valueForUndefinedKey: in any NSObject in your code, this may be the problem if something broke +//#warning If you implement valueForUndefinedKey: in any NSObject in your code, this may be the problem if something broke //TODO: This method needs to be: // 1) Renamed to MR_valueForUndefinedKey: // 2) swizzled in and out only when importing data. // This will be done in a really short update...stay tuned -- (id) valueForUndefinedKey:(NSString *)key +- (id) MR_valueForUndefinedKey:(NSString *)key { return nil; } diff --git a/Source/Categories/NSManagedObject+MagicalDataImport.m b/Source/Categories/NSManagedObject+MagicalDataImport.m index 1a10cd8..33ac480 100644 --- a/Source/Categories/NSManagedObject+MagicalDataImport.m +++ b/Source/Categories/NSManagedObject+MagicalDataImport.m @@ -7,6 +7,9 @@ // #import "CoreData+MagicalRecord.h" +#import + +void swizzle(Class c, SEL orig, SEL new); NSString * const kMagicalRecordImportCustomDateFormatKey = @"dateFormat"; NSString * const kMagicalRecordImportDefaultDateFormatString = @"yyyy-MM-dd'T'HH:mm:ss'Z'"; @@ -168,7 +171,7 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; - (void) MR_importValuesForKeysWithDictionary:(id)objectData { - //swizzle MR_valueForUndefinedKey, [self valueForUndefinedKey] + swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:)); if ([self respondsToSelector:@selector(willImport)]) { [self performSelector:@selector(willImport)]; @@ -180,8 +183,8 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; NSDictionary *relationships = [[self entity] relationshipsByName]; [self MR_setRelationships:relationships forKeysWithDictionary:objectData - withBlock:^(NSRelationshipDescription *relationshipInfo, id objectData) - { + withBlock:^(NSRelationshipDescription *relationshipInfo, id objectData){ + NSManagedObject *relatedObject = nil; if ([objectData isKindOfClass:[NSDictionary class]]) { @@ -194,8 +197,8 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; [relatedObject MR_importValuesForKeysWithDictionary:objectData]; [self MR_addObject:relatedObject forRelationship:relationshipInfo]; - }]; - //swizzle back + }]; + swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:)); if ([self respondsToSelector:@selector(didImport)]) { @@ -205,14 +208,20 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; - (void) MR_updateValuesForKeysWithDictionary:(id)objectData { + swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:)); + if ([self respondsToSelector:@selector(willImport)]) + { + [self performSelector:@selector(willImport)]; + } + NSDictionary *attributes = [[self entity] attributesByName]; [self MR_setAttributes:attributes forKeysWithDictionary:objectData]; NSDictionary *relationships = [[self entity] relationshipsByName]; [self MR_setRelationships:relationships forKeysWithDictionary:objectData - withBlock:^(NSRelationshipDescription *relationshipInfo, id objectData) - { + withBlock:^(NSRelationshipDescription *relationshipInfo, id objectData) { + NSManagedObject *relatedObject = [self MR_findObjectForRelationship:relationshipInfo withData:objectData]; if (relatedObject == nil) @@ -225,7 +234,14 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; } [self MR_addObject:relatedObject forRelationship:relationshipInfo]; - }]; + }]; + + swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:)); + + if ([self respondsToSelector:@selector(didImport)]) + { + [self performSelector:@selector(didImport)]; + } } + (id) MR_importFromDictionary:(id)objectData inContext:(NSManagedObjectContext *)context; @@ -291,3 +307,18 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; } @end + + +void swizzle(Class c, SEL orig, SEL new) +{ + Method origMethod = class_getInstanceMethod(c, orig); + Method newMethod = class_getInstanceMethod(c, new); + if (class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) + { + class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); + } + else + { + method_exchangeImplementations(origMethod, newMethod); + } +} diff --git a/Source/MagicalRecordHelpers.m b/Source/MagicalRecordHelpers.m index 477d5dd..00ea73f 100644 --- a/Source/MagicalRecordHelpers.m +++ b/Source/MagicalRecordHelpers.m @@ -9,7 +9,9 @@ #import static NSString * const kMagicalRecordCategoryPrefix = @"MR_"; +#ifdef MR_SHORTHAND static BOOL methodsHaveBeenSwizzled = NO; +#endif static id errorHandlerTarget = nil; static SEL errorHandlerAction = nil;