Skip to content

Commit

Permalink
Merge branch 'iOS5-only' into 2.0
Browse files Browse the repository at this point in the history
Conflicts:
	MagicalRecord/Categories/NSManagedObject+MagicalDataImport.h
	MagicalRecord/Categories/NSManagedObject+MagicalDataImport.m
	MagicalRecord/Categories/NSManagedObjectContext+MagicalRecord.m
	MagicalRecord/Categories/NSPersistentStore+MagicalRecord.m
	MagicalRecord/Categories/NSPersistentStoreCoordinator+MagicalRecord.m
	Source/Categories/NSManagedObject+MagicalRecord.h
	Source/Categories/NSManagedObject+MagicalRecord.m
	Source/CoreData+MagicalRecord.h
	Source/MagicalRecordHelpers.h
	Source/MagicalRecordHelpers.m
  • Loading branch information
casademora committed Mar 9, 2012
2 parents 7d42e17 + 5053bc8 commit 85fc403
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 119 deletions.
Expand Up @@ -10,6 +10,6 @@
@interface NSEntityDescription (MagicalRecord_DataImport)

- (NSAttributeDescription *) MR_primaryKeyAttribute;
- (NSManagedObject *) MR_createInstanceFromDictionary:(id)objectData inContext:(NSManagedObjectContext *)context;
- (NSManagedObject *) MR_createInstanceFromObject:(id)objectData inContext:(NSManagedObjectContext *)context;

@end
Expand Up @@ -23,7 +23,7 @@ - (NSAttributeDescription *) MR_primaryKeyAttribute;
}


- (NSManagedObject *) MR_createInstanceFromDictionary:(id)objectData inContext:(NSManagedObjectContext *)context
- (NSManagedObject *) MR_createInstanceFromObject:(id)objectData inContext:(NSManagedObjectContext *)context
{
NSManagedObject *relatedObject = [[self class] insertNewObjectForEntityForName:[self name]
inManagedObjectContext:context];
Expand Down
12 changes: 7 additions & 5 deletions MagicalRecord/Categories/NSManagedObject+MagicalDataImport.h
Expand Up @@ -19,19 +19,21 @@ extern NSString * const kMagicalRecordImportRelationshipTypeKey;

@interface NSManagedObject (MagicalRecord_DataImport)

- (void) MR_importValuesForKeysWithObject:(id)objectData;
- (void) MR_updateValuesForKeysWithObject:(id)objectData;
- (NSString *) MR_primaryKeyAttributeName;

- (BOOL) MR_importValuesForKeysWithObject:(id)objectData;
- (BOOL) MR_updateValuesForKeysWithObject:(id)objectData;

+ (id) MR_importFromObject:(id)data;
+ (id) MR_importFromObject:(id)data inContext:(NSManagedObjectContext *)context;

+ (NSArray *) MR_importFromArray:(NSArray *)listOfObjectData;
+ (NSArray *) MR_importFromArray:(NSArray *)listOfObjectData inContext:(NSManagedObjectContext *)context;

+ (id) MR_updateFromObject:(id)objectData;
+ (id) MR_updateFromObject:(id)objectData inContext:(NSManagedObjectContext *)context;

+ (NSArray *) MR_updateFromArray:(NSArray *)listOfObjectData;
+ (NSArray *) MR_updateFromArray:(NSArray *)listOfObjectData inContext:(NSManagedObjectContext *)context;

+ (id) MR_updateFromObject:(id)objectData;
+ (id) MR_updateFromObject:(id)objectData inContext:(NSManagedObjectContext *)context;

@end
169 changes: 99 additions & 70 deletions MagicalRecord/Categories/NSManagedObject+MagicalDataImport.m
Expand Up @@ -20,8 +20,17 @@
NSString * const kMagicalRecordImportRelationshipPrimaryKey = @"primaryRelationshipKey";
NSString * const kMagicalRecordImportRelationshipTypeKey = @"type";


#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

@implementation NSManagedObject (MagicalRecord_DataImport)

- (NSString *) MR_primaryKeyAttributeName;
{
return [[[self entity] MR_primaryKeyAttribute] name];
}

- (id) MR_valueForAttribute:(NSAttributeDescription *)attributeInfo fromObjectData:(NSDictionary *)objectData forKeyPath:(NSString *)keyPath
{
id value = [objectData valueForKeyPath:keyPath];
Expand Down Expand Up @@ -66,7 +75,7 @@ - (BOOL) MR_importValue:(id)value forKey:(NSString *)key
return NO;
}

- (void) MR_setAttributes:(NSDictionary *)attributes forKeysWithDictionary:(NSDictionary *)objectData
- (void) MR_setAttributes:(NSDictionary *)attributes forKeysWithDictionary:(id)objectData
{
for (NSString *attributeName in attributes)
{
Expand Down Expand Up @@ -131,10 +140,7 @@ - (void) MR_addObject:(NSManagedObject *)relatedObject forRelationship:(NSRelati

@try
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[relationshipSource performSelector:selector withObject:relatedObject];
#pragma clang diagnostic pop
}
@catch (NSException *exception)
{
Expand All @@ -150,55 +156,79 @@ - (void) MR_setRelationships:(NSDictionary *)relationships forKeysWithDictionary
{
for (NSString *relationshipName in relationships)
{
if ([self MR_importValue:relationshipData forKey:relationshipName])
{
continue;
}

NSRelationshipDescription *relationshipInfo = [relationships valueForKey:relationshipName];

NSString *lookupKey = [[relationshipInfo userInfo] valueForKey:kMagicalRecordImportRelationshipMapKey] ?: relationshipName;

id relatedObjectData = [relationshipData valueForKey:lookupKey];

if (relatedObjectData == nil || [relatedObjectData isEqual:[NSNull null]])
{
continue;
}

SEL shouldImportSelector = @selector(shouldImport:);
BOOL implementsShouldImport = [self respondsToSelector:shouldImportSelector];

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

if (![self MR_importValue:relatedObjectData forKey:relationshipName])
SEL shouldImportSelector = NSSelectorFromString([NSString stringWithFormat:@"shouldImport%@:", [relationshipName MR_capitalizedFirstCharaterString]]);
BOOL implementsShouldImport = (BOOL)[self respondsToSelector:shouldImportSelector];
void (^establishRelationship)(NSRelationshipDescription *, id) = ^(NSRelationshipDescription *blockInfo, id blockData)
{
if ([relationshipInfo isToMany])
if (!(implementsShouldImport && !(BOOL)[self performSelector:shouldImportSelector withObject:relatedObjectData]))
{
for (id singleRelatedObjectData in relatedObjectData)
{
if (implementsShouldImport && ![[self performSelector:shouldImportSelector withObject:singleRelatedObjectData] boolValue])
{
continue;
}
setRelationshipBlock(relationshipInfo, singleRelatedObjectData);
}
setRelationshipBlock(blockInfo, blockData);
}
else
};

if ([relationshipInfo isToMany])
{
for (id singleRelatedObjectData in relatedObjectData)
{
if (!(implementsShouldImport && !(BOOL)[self performSelector:shouldImportSelector withObject:relatedObjectData]))
{
setRelationshipBlock(relationshipInfo, relatedObjectData);
}
establishRelationship(relationshipInfo, singleRelatedObjectData);
}
}
#pragma clang diagnostic pop
else
{
establishRelationship(relationshipInfo, relatedObjectData);
}
}
}

- (void) MR_importValuesForKeysWithObject:(id)objectData
- (BOOL) MR_preImport:(id)objectData;
{
if ([self respondsToSelector:@selector(shouldImport:)])
{
BOOL shouldImport = (BOOL)[self performSelector:@selector(shouldImport:) withObject:objectData];
if (!shouldImport)
{
// NSLog(@"Not importing: %@", objectData);
return NO;
}
}

if ([self respondsToSelector:@selector(willImport:)])
{
[self performSelector:@selector(willImport:) withObject:objectData];
}
MR_swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:));
return YES;
}

- (BOOL) MR_postImport:(id)objectData;
{
MR_swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:));
if ([self respondsToSelector:@selector(willImport)])
if ([self respondsToSelector:@selector(didImport:)])
{
[self performSelector:@selector(willImport)];
[self performSelector:@selector(didImport:) withObject:objectData];
}
return YES;
}

- (BOOL) MR_importValuesForKeysWithObject:(id)objectData
{
BOOL didStartimporting = [self MR_preImport:objectData];
if (!didStartimporting) return NO;

NSDictionary *attributes = [[self entity] attributesByName];
[self MR_setAttributes:attributes forKeysWithDictionary:objectData];
Expand All @@ -209,44 +239,19 @@ - (void) MR_importValuesForKeysWithObject:(id)objectData
withBlock:^(NSRelationshipDescription *relationshipInfo, id objectData){

NSManagedObject *relatedObject = nil;
if ([objectData isKindOfClass:[NSDictionary class]])
{
// Changed to fix nested updates changing to import operation half way through
relatedObject = [self MR_findObjectForRelationship:relationshipInfo withData:objectData];

if (!relatedObject)
{
relatedObject = [[relationshipInfo destinationEntity] MR_createInstanceFromDictionary:objectData inContext:[self managedObjectContext]];
}
else
{
[relatedObject MR_updateValuesForKeysWithObject:objectData];
}

}
else
{
relatedObject = [self MR_findObjectForRelationship:relationshipInfo withData:objectData];
}
relatedObject = [[relationshipInfo destinationEntity] MR_createInstanceFromObject:objectData inContext:[self managedObjectContext]];
[relatedObject MR_importValuesForKeysWithObject:objectData];

[self MR_addObject:relatedObject forRelationship:relationshipInfo];
}];
MR_swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:));

if ([self respondsToSelector:@selector(didImport)])
{
[self performSelector:@selector(didImport)];
}

return [self MR_postImport:objectData];
}

- (void) MR_updateValuesForKeysWithObject:(id)objectData
- (BOOL) MR_updateValuesForKeysWithObject:(id)objectData
{
MR_swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:));
if ([self respondsToSelector:@selector(willImport)])
{
[self performSelector:@selector(willImport)];
}
BOOL didStartimporting = [self MR_preImport:objectData];
if (!didStartimporting) return NO;

NSDictionary *attributes = [[self entity] attributesByName];
[self MR_setAttributes:attributes forKeysWithDictionary:objectData];
Expand All @@ -260,22 +265,17 @@ - (void) MR_updateValuesForKeysWithObject:(id)objectData
withData:objectData];
if (relatedObject == nil)
{
relatedObject = [[relationshipInfo destinationEntity] MR_createInstanceFromDictionary:objectData inContext:[self managedObjectContext]];
relatedObject = [[relationshipInfo destinationEntity] MR_createInstanceFromObject:objectData inContext:[self managedObjectContext]];
}
else
{
[relatedObject MR_updateValuesForKeysWithObject:objectData];
[relatedObject MR_importValuesForKeysWithObject:objectData];
}

[self MR_addObject:relatedObject forRelationship:relationshipInfo];
}];

MR_swizzle([objectData class], @selector(valueForUndefinedKey:), @selector(MR_valueForUndefinedKey:));

if ([self respondsToSelector:@selector(didImport)])
{
[self performSelector:@selector(didImport)];
}
return [self MR_postImport:objectData];
}

+ (id) MR_importFromObject:(id)objectData inContext:(NSManagedObjectContext *)context;
Expand Down Expand Up @@ -356,7 +356,7 @@ + (NSArray *) MR_updateFromArray:(NSArray *)listOfObjectData inContext:(NSManage

NSDictionary *objectData = (NSDictionary *)obj;

NSManagedObject *dataObject = [self MR_updateFromObject:objectData inContext:localContext];
NSManagedObject *dataObject = [self MR_importFromObject:objectData inContext:localContext];

if ([context obtainPermanentIDsForObjects:[NSArray arrayWithObject:dataObject] error:nil])
{
Expand All @@ -368,8 +368,37 @@ + (NSArray *) MR_updateFromArray:(NSArray *)listOfObjectData inContext:(NSManage
return [self MR_findAllWithPredicate:[NSPredicate predicateWithFormat:@"self IN %@", objectIDs] inContext:context];
}


+ (NSArray *) MR_updateFromArray:(NSArray *)listOfObjectData;
{
return [self MR_updateFromArray:listOfObjectData inContext:[NSManagedObjectContext MR_defaultContext]];
}

+ (NSArray *) MR_updateFromArray:(NSArray *)listOfObjectData inContext:(NSManagedObjectContext *)context;
{
NSMutableArray *objectIDs = [NSMutableArray array];

[MRCoreDataAction saveDataWithBlock:^(NSManagedObjectContext *localContext)
{
[listOfObjectData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

NSDictionary *objectData = (NSDictionary *)obj;

NSManagedObject *dataObject = [self MR_updateFromObject:objectData inContext:localContext];

if ([context obtainPermanentIDsForObjects:[NSArray arrayWithObject:dataObject] error:nil])
{
[objectIDs addObject:[dataObject objectID]];
}
}];
}];

return [self MR_findAllWithPredicate:[NSPredicate predicateWithFormat:@"self IN %@", objectIDs] inContext:context];
}

@end

#pragma clang diagnostic pop

void MR_swizzle(Class c, SEL orig, SEL new)
{
Expand Down

0 comments on commit 85fc403

Please sign in to comment.