Datos básicos: la forma más rápida de eliminar todas las instancias de una entidad

Resuelto Adaromas asked hace 54 años • 29 respuestas

Estoy usando Core Data para conservar localmente los resultados de una llamada de servicios web. El servicio web devuelve el modelo de objeto completo para, digamos, "Coches"; podrían ser unos 2000 de ellos (y no puedo hacer que el servicio web devuelva menos de 1 o TODOS los coches).

La próxima vez que abra mi aplicación, quiero actualizar la copia persistente de Core Data llamando nuevamente al servicio web para todos los automóviles; sin embargo, para evitar duplicados, primero necesitaría borrar todos los datos en el caché local.

¿Existe una forma más rápida de purgar TODAS las instancias de una entidad específica en el contexto del objeto administrado (por ejemplo, todas las entidades de tipo "CAR"), o necesito consultarlas, luego iterar sobre los resultados para eliminar cada una y luego guardarlas?

Lo ideal sería simplemente decir eliminar todo donde la entidad sea Blah.

Adaromas avatar Jan 01 '70 08:01 Adaromas
Aceptado

iOS 9 y posterior:

iOS 9 agregó una nueva clase llamada NSBatchDeleteRequestque le permite eliminar fácilmente objetos que coincidan con un predicado sin tener que cargarlos todos en la memoria. Así es como lo usarías:

veloz 5

let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Car")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

do {
    try myPersistentStoreCoordinator.execute(deleteRequest, with: myContext)
} catch let error as NSError {
    // TODO: handle the error
}

C objetivo

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Car"];
NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];

NSError *deleteError = nil;
[myPersistentStoreCoordinator executeRequest:delete withContext:myContext error:&deleteError];

Puede encontrar más información sobre las eliminaciones por lotes en la sesión "Novedades en datos básicos" de la WWDC 2015 (a partir de las 14:10 aproximadamente).

iOS 8 y anteriores:

Tráelos todos y elimínalos todos:

NSFetchRequest *allCars = [[NSFetchRequest alloc] init];
[allCars setEntity:[NSEntityDescription entityForName:@"Car" inManagedObjectContext:myContext]];
[allCars setIncludesPropertyValues:NO]; //only fetch the managedObjectID

NSError *error = nil;
NSArray *cars = [myContext executeFetchRequest:allCars error:&error];
[allCars release];
//error handling goes here
for (NSManagedObject *car in cars) {
  [myContext deleteObject:car];
}
NSError *saveError = nil;
[myContext save:&saveError];
//more error handling here
Dave DeLong avatar Sep 05 '2009 15:09 Dave DeLong

Restablecer entidad en 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")
        }
    }
roy avatar May 13 '2017 11:05 roy

Un poco más limpio y universal: agregue este método:

- (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];
}
Jon - LBAB avatar Sep 12 '2014 14:09 Jon - LBAB

Actualización de Swift 4, iOS 12 y Xcode 10

100% funcionando solo corta y pega

Simplemente coloque esta función en la clase relevante y llame a esta función self.deleteData()en viewDidLoad()o en cualquier lugar o debajo de una función o un botón para que al hacer clic en un botón todos los datos de la entidad se eliminen y reemplacen "myEntity" como su entidad que ha definido en su datos centrales

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)")
    }
}
Xcodian Solangi avatar Jan 17 '2018 05:01 Xcodian Solangi

Esta es una pregunta similar a la de aquí y alguien sugirió configurar una regla de eliminación de relaciones para que solo tenga que eliminar un objeto. Entonces, si tiene o puede crear una entidad con una relación de muchos con los autos y establece la regla de eliminación en cascada cuando elimine la entidad superior, todos los autos también se eliminarán. Esto puede ahorrar algo de tiempo de procesamiento ya que no es necesario seguir los pasos necesarios para cargar TODOS los autos. En un conjunto de datos más grande esto podría ser absolutamente necesario.

T. Markle avatar Apr 20 '2011 15:04 T. Markle