문제

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

다른 팁

As it seems, you already have an array of Feed objects and an array of CoreData objects, both sorted by the same attribute "name" in increasing order.

You can update/insert/delete the CoreData objects from the Feed objects with a single loop over both arrays using two independent pointers into the arrays.

The pseudo-code looks like this:

i1 = 0; // pointer into Feed array
i2 = 0; // pointer into CD (CoreData objects) array
while (i1 < Feed.count && i2 < CD.count) {
    if (Feed[i1].name < CD[i2].name) {
        // Feed[i1] is not in CD array
        "Insert Feed[i1] as new Core Data object"
        i1++;
    } else if (Feed[i1].name > CD[i2].name) {
        // CD[i2].name is not in Feed array
        "Delete CD[i2] from Core Data"
        i2++;
    } else {
        "Update CD[i2] from Feed[i1]"
        i1++, i2++;
    }
}

// Add remaining objects from Feed array:
while (i1 < Feed.count) {
        "Insert Feed[i1] as new Core Data object"
        i1++;
}

// Remove remaining Core Data objects
while (i2 < CD.count) {
        "Delete CD[i2] from Core Data"
        i2++;
}

In your example:

    Feed      CoreData
    ----      --------
i1->A     i2->A              same name, CoreData object is updated, i1++, i2++
    B         B
    D         C
              D
    Feed      CoreData
    ----      --------
    A         A
i1->B     i2->B              same name, CoreData object is updated, i1++, i2++
    D         C
              D
    Feed      CoreData
    ----      --------
    A         A
    B         B
i1->D     i2->C              "D" > "C", CoreData object is deleted, i2++
              D
    Feed      CoreData
    ----      --------
    A         A
    B         B
i1->D         C
          i2->D              same name, CoreData object is updated, i1++, i2++
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top