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

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

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

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


当前回答

Swift 4, iOS 12和Xcode 10更新

100%工作,只是剪切和粘贴

只要把这个函数放在相关的类中,并在viewDidLoad()或任何地方或在一个函数或按钮下调用这个函数self.deleteData(),这样通过单击一个按钮,所有来自实体的数据都应该被删除,并替换“myEntity”作为你在核心数据中定义的实体

func deleteData() {
    let appDel:AppDelegate = (UIApplication.shared.delegate as! AppDelegate)
    let context:NSManagedObjectContext = appDel.persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "myEntity")
    fetchRequest.returnsObjectsAsFaults = false         
    do {
        let results = try context.fetch(fetchRequest)
        for managedObject in results {
            if let managedObjectData: NSManagedObject = managedObject as? NSManagedObject {
                context.delete(managedObjectData)
            }
        }
    } catch let error as NSError {
        print("Deleted all my data in myEntity error : \(error) \(error.userInfo)")
    }
}

其他回答

更干净和通用一点:添加这个方法:

- (void)deleteAllEntities:(NSString *)nameEntity
{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:nameEntity];
    [fetchRequest setIncludesPropertyValues:NO]; //only fetch the managedObjectID

    NSError *error;
    NSArray *fetchedObjects = [theContext executeFetchRequest:fetchRequest error:&error];
    for (NSManagedObject *object in fetchedObjects)
    {
        [theContext deleteObject:object];
    }

    error = nil;
    [theContext save:&error];
}

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

 - (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];
    }
}

iOS 9.0及以上版本:

NSBatchDeleteRequest用于删除核心数据中的记录。它的工作速度非常快,从一个实体删除所有记录所需的时间更少。它需要NSFetchRequest作为参数。如果你想从一个实体删除所有记录,你可以使用它,它为我工作。

let manageObject:NSManagedObjectContext = appDelegateObject.managedObjectContext

let fetchRequest = NSFetchRequest(entityName: “EnityName”)

let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

let persistCor:NSPersistentStoreCoordinator = appDelegateObject.persistentObject
 do {
        try persistCor.executeRequest(deleteRequest, withContext: manageObject)
        try manageObject.save()
    } catch {
        print(error?.localizedDescription)
    }

Swift 4, iOS 10+ 静态函数,可以应用于任何实体删除其所有数据

protocol NSManagedObjectHelper {
}
extension NSManagedObject: NSManagedObjectHelper {
}
extension NSManagedObjectHelper where Self: NSManagedObject {
    static func removeAllObjectsInContext(_ managedContext: NSManagedObjectContext) {
        let request: NSFetchRequest = NSFetchRequest(entityName: String(describing: self))
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: request)
        do {
            deleteRequest.resultType = .resultTypeObjectIDs//to clear objects from memory
            let result = try managedContext.execute(deleteRequest) as? NSBatchDeleteResult
            if let objectIDArray = result?.result as? [NSManagedObjectID] {
                let changes = [NSDeletedObjectsKey : objectIDArray]
                /*By calling mergeChangesFromRemoteContextSave, all of the NSManagedObjectContext instances that are referenced will be notified that the list of entities referenced with the NSManagedObjectID array have been deleted and that the objects in memory are stale. This causes the referenced NSManagedObjectContext instances to remove any objects in memory that are loaded which match the NSManagedObjectID instances in the array.*/
                NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [managedContext])
            }
            try managedContext.save()
        } catch let error {
            print(error)
        }
    }
}

“房间”是一个实体

Room.removeAllObjectsInContext(self.persistentContainer.viewContext)

在20191025编辑:如果我们在同一个项目中使用多个目标,"Self.fetchRequest()"指令可能会导致问题。所以替换为NSFetchRequest(entityName: String(description: self))

Swift 3解决方案与iOS 9 'NSBatchDeleteRequest'和回退到早期的iOS版本,作为'NSManagedObjectContext'的扩展实现。苹果参考https://developer.apple.com/library/content/featuredarticles/CoreData_Batch_Guide/BatchDeletes/BatchDeletes.html

extension NSManagedObjectContext {
    func batchDeleteEntities<T: NSManagedObject>(ofType type: T.Type) throws {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: type.self))
        if #available(iOS 9.0, *) {
            let request = NSBatchDeleteRequest(fetchRequest: fetchRequest)
            let result = try execute(request) as? NSBatchDeleteResult
            if let objectIDArray = result?.result as? [NSManagedObjectID] {
                let changes = [NSDeletedObjectsKey: objectIDArray]
                NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [self])
            }
        } else {
            fetchRequest.includesPropertyValues = false
            let results = try fetch(fetchRequest)
            if let actualResults = results as? [NSManagedObject], !actualResults.isEmpty {
                actualResults.forEach { delete($0) }
            }
        }
    }
}