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

10voto

T. Markle Points 667

C'est une question similaire à celle aquí et quelqu'un a suggéré de mettre en place une règle de suppression de relation afin que vous ne deviez supprimer qu'un seul objet. Ainsi, si vous avez ou pouvez créer une entité avec une relation to-many avec les voitures et que vous définissez la règle de suppression en cascade lorsque vous supprimez l'entité supérieure, toutes les voitures seront également supprimées. Cela peut permettre de gagner du temps de traitement puisque vous n'avez pas à effectuer les étapes de chargement de TOUTES les voitures. Dans un ensemble de données plus important, cela pourrait être absolument nécessaire.

1 votes

Je viens d'essayer ceci sur mon projet actuel avec environ 600 objets de données de base. Lorsque je les ai encapsulés dans un autre objet avec cascade, la suppression a pris environ 9,1 secondes. Si j'utilise la méthode suggérée par Dave, la suppression prend environ 8,7 secondes. Ce n'est pas une différence notable pour moi.

10voto

Xcodian Solangi Points 1130

Mise à jour de Swift 4, iOS 12 et Xcode 10

100% fonctionnel, il suffit de couper et coller

Il suffit de placer cette fonction dans la classe concernée et d'appeler cette fonction self.deleteData() en viewDidLoad() ou n'importe où ou sous une fonction ou un bouton de sorte que, en cliquant sur un bouton, toutes les données de l'entité soient supprimées et remplacent "myEntity" par l'entité que vous avez définie dans vos données de base.

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)")
    }
}

8voto

Mr Q.C. Points 385

Une bonne réponse a déjà été postée, ce n'est qu'une recommandation !

Une bonne façon de procéder serait d'ajouter une catégorie à l'adresse suivante NSManagedObject et implémenter une méthode comme je l'ai fait :

Fichier d'en-tête (par exemple NSManagedObject+Ext.h )

@interface NSManagedObject (Logic)

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

@end

Fichier de code : (par exemple, 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

... la seule chose à faire est de récupérer le managedObjectContext du délégué de l'application, ou de tout autre endroit où il se trouve ;)

ensuite vous pouvez l'utiliser comme :

[NSManagedObject deleteAllFromEntity:@"EntityName"];

une optimisation supplémentaire pourrait consister à supprimer le paramètre pour l'entityname et à obtenir le nom à partir du clazzname. cela conduirait à l'utilisation :

[ClazzName deleteAllFromEntity];

un impl plus propre (comme catégorie de 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

L'usage alors :

[managedObjectContext deleteAllFromEntity:@"EntityName"];

6voto

Karun Kumar Points 146

iOS 10 et plus

Fonctionne avec toutes les versions. Passez le nom de l'entité et faites une itération pour supprimer toutes les entrées et sauvegarder le contexte.

func deleteData(entityToFetch: String, completion: @escaping(_ returned: Bool) ->()) {
        let context = NSManagedObjectContext()
        context = your managedObjectContext

        let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
        fetchRequest.entity = NSEntityDescription.entity(forEntityName: entityToFetch, in: context)
        fetchRequest.includesPropertyValues = false
         do {   
            let results = try context.fetch(fetchRequest) as! [NSManagedObject]
            for result in results {
                context.delete(result)
            }
            try context.save()
            completion(true)
        } catch {
            completion(false)
            print("fetch error -\(error.localizedDescription)")
        }
    }

6voto

SwiftDeveloper Points 2288

Swift 3.X y Swift 4.X C'est facile. Changez seulement VotreTable

    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "YourTable")
    fetchRequest.returnsObjectsAsFaults = false

    do
    {
        let results = try context.fetch(fetchRequest)
        for managedObject in results
        {
            let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
            context.delete(managedObjectData)
        }
    } catch let error as NSError {
        print("Detele all my data in \(entity) error : \(error) \(error.userInfo)")
    }

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