424 votes

Données de base : Le moyen le plus rapide de supprimer toutes les instances d'une entité

J'utilise Core Data pour conserver localement les résultats d'un appel de services Web. Le service Web renvoie le modèle d'objet complet pour, disons, "Cars" - il peut y en avoir environ 2000 (et je ne peux pas faire en sorte que le service Web renvoie moins de 1 ou TOUTES les voitures.

La prochaine fois que j'ouvre mon application, je veux rafraîchir la copie persistante de Core Data en appelant à nouveau le service Web pour toutes les voitures, mais pour éviter les doublons, je dois d'abord purger toutes les données dans le cache local.

Existe-t-il un moyen plus rapide de purger TOUTES les instances d'une entité spécifique dans le contexte de l'objet géré (par exemple, toutes les entités de type "CAR"), ou dois-je les interroger, puis itérer dans les résultats pour supprimer chacune d'entre elles, puis sauvegarder ?

Idéalement, je pourrais juste dire de supprimer tout ce qui est entité de Blah.

1 votes

Vous pourriez utiliser une base de données en mémoire

768voto

Dave DeLong Points 156978

IOS 9 et versions ultérieures :

iOS 9 a ajouté une nouvelle classe appelée NSBatchDeleteRequest qui vous permet de supprimer facilement les objets correspondant à un prédicat sans avoir à les charger tous en mémoire. Voici comment l'utiliser :

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

Objectif-C

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

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

Vous trouverez plus d'informations sur les suppressions par lots dans le document intitulé Session "What's New in Core Data" de la WWDC 2015 (à partir de ~14:10).

iOS 8 et antérieurs :

Récupérez-les tous et supprimez-les tous :

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

74 votes

Je configurerais également la récupération pour qu'elle ne récupère que le NSManagedObjectID afin de réduire toute surcharge due au chargement de la structure complète de l'objet.

38 votes

Il n'est pas évident de savoir comment récupérer uniquement le NSMangagedObjectID utilisez [allCars setIncludesPropertyValues:NO] ; (et ne vous embêtez pas à chercher comment créer une NSPropertyDescription pour l'ID de l'objet !)

1 votes

Juste une info le code ci-dessus ne fonctionnerait pas pour moi à moins que je passe à l'executeFetchRequest un 'error:&error' aussi.

49voto

roy Points 3200

Réinitialisation de l'entité dans 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")
        }
    }

33voto

Numereyes Points 76

Un peu plus propre et universel : Ajouter cette méthode :

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

16voto

Gaurav Sharma Points 647

Pour Swift 2.0 :

class func clearCoreData(entity:String) {
  let fetchRequest = NSFetchRequest()
  fetchRequest.entity = NSEntityDescription.entityForName(entity, inManagedObjectContext: moc!)
  fetchRequest.includesPropertyValues = false
  do {
    if let results = try moc!.executeFetchRequest(fetchRequest) as? [NSManagedObject] {
      for result in results {
        moc!.deleteObject(result)
      }

      try moc!.save()
    }
  } catch {
    LOG.debug("failed to clear core data")
  }
}

12voto

Ixx Points 7104

Swift :

let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
fetchRequest.includesPropertyValues = false

var error:NSError?
if let results = context.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObject] {
    for result in results {
        context.deleteObject(result)
    }

    var error:NSError?
    if context.save(&error) {
        // do something after save

    } else if let error = error {
        println(error.userInfo)
    }

} else if let error = error {
    println("error: \(error)")
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X