我使用Core Data在本地持久化Web服务调用的结果。web服务返回完整的对象模型,比如说,“Cars”——可能有2000辆车(我不能让web服务返回小于1辆或ALL辆的任何东西。

下次打开应用程序时,我希望通过再次调用所有汽车的Web服务来刷新Core Data持久化副本,但是为了防止重复,我需要首先清除本地缓存中的所有数据。

是否有一种更快的方法来清除管理对象上下文中特定实体的所有实例(例如,类型为“CAR”的所有实体),或者我需要查询它们调用,然后遍历结果删除每个,然后保存?

理想情况下,我可以说删除实体所在的所有地方等等。


当前回答

为什么不将接收到的数据与现有缓存一起折叠呢?否则它就不是真正的“刷新”,而是“重新开始”,你也可以删除SQLLite文件并重新开始(假设你没有持久化其他数据)。

其他回答

如果实体包含很多条目,最好的方法是这样,因为它节省内存

 - (void)deleteAll:(NSManagedObjectContext *)managedObjectContext entityName:(NSString *)entityName
{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [managedObjectContext setUndoManager:nil];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setIncludesPropertyValues:NO];
    [fetchRequest setFetchLimit:100]; // you can change this number if you want
    NSError *error;
    NSArray *items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    while ([items count] > 0) {
        @autoreleasepool {
            for (NSManagedObject *item in items) {
                [managedObjectContext deleteObject:item];
            }
            if (![managedObjectContext save:&error]) {
                NSLog(@"Error deleting %@ - error:%@",self.entityName, error);
            }
        }
        items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    }
}

这是一个类似的问题,有人建议设置一个关系删除规则,这样你只需要删除一个对象。因此,如果您已经或可以创建一个与汽车具有多对关系的实体,并将删除规则设置为级联,当您删除更高的实体时,所有的汽车也将被删除。这可以节省一些处理时间,因为您不必执行加载所有汽车的步骤。在更大的数据集中,这可能是绝对必要的。

在Swift 3中重置实体:

func resetAllRecords(in entity : String) // entity = Your_Entity_Name
    {

        let context = ( UIApplication.shared.delegate as! AppDelegate ).persistentContainer.viewContext
        let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
        do
        {
            try context.execute(deleteRequest)
            try context.save()
        }
        catch
        {
            print ("There was an error")
        }
    }

上面的答案很好地说明了如何删除“Cars”。

然而,我想用这个答案来挑战这种方法本身:

1- SQLite CoreData是一个关系数据库。在这种情况下,如果没有任何关联,我建议不要使用CoreData,而改用文件系统,或者将数据保存在内存中。

2-在其他例子中,“Car”实体有其他关系,因此CoreData,我建议不要把2000辆车作为根实体。相反,我会给它们一个父实体,比如说"CarsRepository"实体。然后,您可以给“Car”实体一个一对多的关系,只需在下载新车时替换该关系以指向新车。向关系中添加正确的删除规则可以确保模型的完整性。

一个很好的答案已经贴出来了,这只是一个推荐!

一个好方法是添加一个类别到NSManagedObject和实现一个方法,就像我做的:

头文件(例如NSManagedObject+Ext.h)

@interface NSManagedObject (Logic)

+ (void) deleteAllFromEntity:(NSString*) entityName;

@end

代码文件:(例如NSManagedObject+Ext.m)

@implementation NSManagedObject (Logic)

+ (void) deleteAllFromEntity:(NSString *)entityName {
    NSManagedObjectContext *managedObjectContext = [AppDelegate managedObjectContext];
    NSFetchRequest * allRecords = [[NSFetchRequest alloc] init];
    [allRecords setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext]];
    [allRecords setIncludesPropertyValues:NO];
    NSError * error = nil;
    NSArray * result = [managedObjectContext executeFetchRequest:allRecords error:&error];
    for (NSManagedObject * profile in result) {
        [managedObjectContext deleteObject:profile];
    }
    NSError *saveError = nil;
    [managedObjectContext save:&saveError];
}

@end

... 你唯一要做的就是从应用程序委托获取managedObjectContext,或者你在哪里都有它;)

之后你可以这样使用它:

[NSManagedObject deleteAllFromEntity:@"EntityName"];

进一步的优化可以是删除entityname的参数,而从clazzname获取名称。这将导致使用:

[ClazzName deleteAllFromEntity];

一个更干净的impl(作为NSManagedObjectContext的类别):

@implementation NSManagedObjectContext (Logic)

- (void) deleteAllFromEntity:(NSString *)entityName {
    NSFetchRequest * allRecords = [[NSFetchRequest alloc] init];
    [allRecords setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:self]];
    [allRecords setIncludesPropertyValues:NO];
    NSError * error = nil;
    NSArray * result = [self executeFetchRequest:allRecords error:&error];
    for (NSManagedObject * profile in result) {
        [self deleteObject:profile];
    }
    NSError *saveError = nil;
    [self save:&saveError];
}

@end

那时的用法:

[managedObjectContext deleteAllFromEntity:@"EntityName"];