简体   繁体   中英

Core Data: How to delete objects that are not in new data

I've learned about Core Data from Stanford Lecture series for iOS5 and iOS7, and I've successfully made 3 different apps using Core Data. But I always had a problem that I could not solve regarding to Core Data:

Is there a way you could delete objects in Core data if those objects are not present in new data?

For example, say I am developing a museum app. And if some of old, Core-Data objects in an iPhone are not present in the new data received from Internet, it means that those old objects are no longer needed in the app and should be deleted. How can u delete these? Updating and creating new objects is easy, but with Core Data, deleting ones with process of elimination is not possible!

I could delete all object and insert the new object, but only a few objects are modified, changed, or deleted each time. So delaying everything and inserting everything again is not an effective solution, especially considering you are fetching around 200 objects each time.

Assuming that

  • your Core Data entity has an attribute "unique_id" that uniquely identifies each object, and
  • the server response is stored as an array of dictionaries (eg from a JSON response) where each dictionary also contains the "unique_id",

then you can do the following: First, create an array of all unique ids from the new objects from the server:

NSArray *uniqueIds = [serverResponse valueForKey:@"unique_id"];

Then fetch all objects with ids that are not in this array. This can be done with a single fetch request:

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"YourEntity"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT unique_id IN %@", uniqueIds];
request.predicate = predicate;
NSError *error;
NSArray *outdatedObjects = [context executeFetchRequest:request error:&error];
if (outdatedObjects == nil) {
    // handle error ...
}

Finally, delete the outdated objects:

for (YourEntity *obj in outdatedObjects) {
    [context deleteObject:obj];
}
if (![context save:&error]) {
   // handle error ...
}

You can fetch all existing objects, loop through them and check against your fetched objects. If the old object isn't present there, remove it from CoreData. Here is some pseudo code how I did it in my app:

    NSMutableSet *objectsToDelete = // Existing CoreData objects
    NSMutableSet *updatedObjects = [NSMutableSet set];

    // Loop over your webservice response objects
    for (...) {
        // Compare to existing objects to check if it's a new object
        // If it is new add it to the updated objects set:
        if (updated) {
        [updatedObjects addObject:webserviceObject];

        } else {
            // New object, insert it into CoreData
        }
    }

    // Calculate deleted objects
    [objectsToDelete minusSet:updatedObjects];
    for (NSManagedObject *obj in objectsToDelete) {
        [obj delete];
    }

    // Persist your changes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM