核心数据:如何删除不在新数据中的对象

时间:2021-11-27 16:56:16

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:

我从iOS5和iOS7的Stanford Lecture系列中学到了Core Data,并且我使用Core Data成功制作了3个不同的应用程序。但我总是遇到一个我无法解决的关于核心数据的问题:

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

有没有办法可以删除Core数据中的对象,如果新数据中没有这些对象?

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!

例如,假设我正在开发一个博物馆应用程序。如果iPhone中的某些旧的Core-Data对象不存在于从Internet接收的新数据中,则意味着应用程序中不再需要这些旧对象,应将其删除。你怎么能删除这些?更新和创建新对象很简单,但使用Core Data,删除具有删除过程的对象是不可能的!

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.

我可以删除所有对象并插入新对象,但每次只修改,更改或删除一些对象。因此,延迟一切并再次插入所有内容并不是一种有效的解决方案,特别是考虑到每次获取大约200个对象。

2 个解决方案

#1


5  

Assuming that

  • your Core Data entity has an attribute "unique_id" that uniquely identifies each object, and
  • 您的Core Data实体具有唯一标识每个对象的属性“unique_id”,以及

  • the server response is stored as an array of dictionaries (e.g. from a JSON response) where each dictionary also contains the "unique_id",
  • 服务器响应存储为字典数组(例如,来自JSON响应),其中每个字典还包含“unique_id”,

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

然后,您可以执行以下操作:首先,从服务器的新对象创建一个包含所有唯一ID的数组:

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:

然后使用不在此数组中的ID获取所有对象。这可以通过单个提取请求完成:

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 ...
}

#2


2  

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:

您可以获取所有现有对象,遍历它们并检查所获取的对象。如果旧对象不存在,请将其从CoreData中删除。这是一些伪代码我是如何在我的应用程序中做到的:

    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

#1


5  

Assuming that

  • your Core Data entity has an attribute "unique_id" that uniquely identifies each object, and
  • 您的Core Data实体具有唯一标识每个对象的属性“unique_id”,以及

  • the server response is stored as an array of dictionaries (e.g. from a JSON response) where each dictionary also contains the "unique_id",
  • 服务器响应存储为字典数组(例如,来自JSON响应),其中每个字典还包含“unique_id”,

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

然后,您可以执行以下操作:首先,从服务器的新对象创建一个包含所有唯一ID的数组:

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:

然后使用不在此数组中的ID获取所有对象。这可以通过单个提取请求完成:

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 ...
}

#2


2  

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:

您可以获取所有现有对象,遍历它们并检查所获取的对象。如果旧对象不存在,请将其从CoreData中删除。这是一些伪代码我是如何在我的应用程序中做到的:

    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