ioscore-datansenumerator

Delete object from Core Data if deleted from the feed


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.


Solution

  • 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);
    }