Consider the following correlation between dictionary objects in a feed and sorted entities in core data:
Feed CoreData
---- --------
A A
B B
C C
D D
As I'm enumerating the feed, I check if A's [stringForKey:@"name"]
isEqualTo A.name
in the entity. If it's a match, I update the entity. If it's not, I insert a new entity into CoreData.
This works fine for updating and inserting, but not for deletion. Consider that object C is removed from the feed:
Feed CoreData
---- --------
A A
B B
D C
D
When I get to "D" in the feed, it will see that object "C" in CoreData is not a match and create a new object D. So I have two problems now: I have two "D" objects, and object "C" does not get removed from CoreData.
So while I want to end up with this:
Feed CoreData
---- --------
A A
B B
D D
What I currently get is this:
Feed CoreData
---- --------
A A
B B
D C
D
D
This must be a common issue so I'm wondering what the best practice is here for determining when to remove entities from Core Data.
This is what I do when I loop through items to determine whether to update, insert, or delete:
-(void)updateWithJSON:(id)JSON
{
//Get an array of all related managed objects
NSMutableArray *allContacts = [[NSMutableArray alloc] initWithArray:[self getAllContacts]];
//Loop through each object downloaded from the server
for (NSDictionary *objectInfo in [JSON objectForKey:@"Contacts"])
{
NSString *objectKey = [objectInfo objectForKey:@"BackendID"];
//Get the managed object for the objectKey
Contact *contact = [[allContacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"backendID == %@", objectKey]] lastObject];
//If the object is nil, then insert the object
if (contact == nil)
{
NSLog(@"Object with key %@ is new.", objectKey);
contact = [[Contact alloc] initWithEntity:[NSEntityDescription entityForName:@"Contact" inManagedObjectContext:self.managedObjectContext] insertIntoManagedObjectContext:self.managedObjectContext];
contact.backendID = objectKey;
}
//Assign property values
contact.firstName = [objectInfo objectForKey:@"FirstName"];
contact.lastName = [objectInfo objectForKey:@"LastName"];
contact.jobTitle = [objectInfo objectForKey:@"JobTitle"];
contact.department = [objectInfo objectForKey:@"Department"];
contact.email = [objectInfo objectForKey:@"Email"];
contact.fax = [objectInfo objectForKey:@"Fax"];
contact.primaryPhone = [objectInfo objectForKey:@"PrimaryPhone"];
contact.secondaryPhone = [objectInfo objectForKey:@"SecondaryPhone"];
//Remove the object from the array of all the objects
if ([allContacts containsObject:contact])
[allContacts removeObject:contact];
}
//Delete any objects that still remain in the array (means they were deleted server-side
for (Contact *contact in allContacts) {
NSLog(@"Removing Contact with key %@", contact.backendID);
[self.managedObjectContext deleteObject:contact];
}
NSError *error = nil;
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext save:&error];
if (error)
NSLog(@"Error Saving Contacts: %@", error.localizedDescription);
}