Core Data: le moyen le plus rapide de supprimer toutes les instances d'une entité

383

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" - pourrait être environ 2000 d'entre eux (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'ouvrirai mon application, je souhaite actualiser la copie persistante des données de base en appelant à nouveau le service Web pour toutes les voitures, mais pour éviter les doublons, je devrais d'abord purger toutes les données du 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 par appel, puis parcourir les résultats pour supprimer chacune, puis enregistrer?

Idéalement, je pourrais simplement dire supprimer tout où l'entité est Blah.

Adaromas
la source
Vous pouvez utiliser une base de données en mémoire
J. Doe

Réponses:

718

iOS 9 et versions ultérieures:

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

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

Plus d'informations sur les suppressions de lots peuvent être trouvées dans la session "Quoi de neuf dans les données de base" de WWDC 2015 (à partir de ~ 14: 10).

iOS 8 et versions antérieures:

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
Dave DeLong
la source
74
Je voudrais également configurer la récupération pour récupérer uniquement le NSManagedObjectID pour réduire toute surcharge due au chargement dans la structure d'objet complète.
Marcus S. Zarra
38
Il n'est pas évident de savoir comment récupérer uniquement le NSMangagedObjectID .. use [allCars setIncludesPropertyValues: NO]; (et ne vous embêtez pas à chercher comment créer une NSPropertyDescription pour l'ID d'objet!)
ohhorob
6
Désolé pour la question des débutants: devez-vous enregistrer le contexte après la fin de la boucle for? par exemple [myContext save];
Steve
6
Une nouvelle installation dans Core Data pour rendre cela plus efficace? Il s'agit d'un problème grave pour mon application, qui est déjà loin du portage vers Core Data. Cela prend plusieurs secondes pour supprimer les 4000 entrées d'une seule table parmi plusieurs. C'est trop long pour que l'utilisateur attende. La même demande directement avec sqlite semble instantanée.
David
4
@DaveDeLong Comment NSBatchDeleteRequest peut déclencher le délégué NSFetchedResultsController? J'essaye presque tout, mais rien ne se passe.
Foriger
36

Réinitialiser 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")
        }
    }
roy
la source
32

Un peu plus propre et universel: Ajoutez 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];
}
Jon - LBAB
la source
16

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")
  }
}
Gaurav Sharma
la source
12

Rapide:

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)")
}
Ixx
la source
1
Cette réponse devrait être mise à jour avec la nouvelle gestion des erreurs try / catch
Suragch
10

Il s'agit d'une question similaire à celle ici et quelqu'un a suggéré de configurer une règle de suppression de relation afin que vous n'ayez à supprimer qu'un seul objet. Donc, si vous avez ou pouvez créer une entité avec une relation to-many avec les voitures et définir la règle de suppression en cascade lorsque vous supprimez l'entité supérieure, toutes les voitures seront également supprimées. Cela peut économiser du temps de traitement car 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.

T. Markle
la source
1
Je viens de l'essayer 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, il a fallu environ 9,1 secondes pour les supprimer. Si j'ai utilisé la méthode suggérée par Dave, il faut environ 8,7 secondes pour supprimer. Pas une différence notable pour moi.
Andrew Zimmer
8

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

Un bon moyen serait simplement d'ajouter une catégorie NSManagedObjectet d'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 que vous devez faire est d'obtenir le managedObjectContext du délégué de l'application, ou où tout ce que vous avez;)

ensuite vous pouvez l'utiliser comme:

[NSManagedObject deleteAllFromEntity:@"EntityName"];

une autre optimisation pourrait être que vous supprimiez le paramètre pour le nom d'entité et que vous obteniez le nom à la place du nom de clazz. cela conduirait à l'utilisation:

[ClazzName deleteAllFromEntity];

un impl plus propre (comme catégorie à 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'utilisation alors:

[managedObjectContext deleteAllFromEntity:@"EntityName"];
Erhard Dinhobl
la source
1
Désolé, mais ce [AppDelegate managedObjectContext]n'est pas nécessairement une "architecture propre" .. ;-)
Daniel Rinser
Ok, c'est vrai. Son code ci-dessus est basé sur un managedObjectContext. le principal;) Dans le code multithread, je fusionne normalement le MOC principal du délégué de l'application aux autres
Erhard Dinhobl
1
@DanielRinser peut êtredeleteAllFromEntity: inManagedObjectContext:
Mohamed Elkassas
Oui. Mieux serait de changer la méthode deleteAllFromEntity d'une méthode de classe à une méthode d'objet. vous pouvez alors appeler deleteAllFromEntity directement sur une instance MOC.
Erhard Dinhobl
7

Mise à jour Swift 4, iOS 12 et Xcode 10

100% de travail, il suffit de couper et coller

Mettez simplement cette fonction dans la classe appropriée et appelez cette fonction self.deleteData()dans viewDidLoad()ou n'importe où ou sous une fonction ou un bouton afin qu'en cliquant sur un bouton toutes les données de l'entité soient supprimées et remplacez "myEntity" comme votre entité que vous avez définie dans votre 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)")
    }
}
Xcodian Solangi
la source
Merci, mais pourquoi le concept NSBatchDeleteRequest ne fonctionne pas? une idée.
Suresh Durishetti
@SureshDurishetti avez-vous importé CoreData dans votre classe?
Xcodian Solangi
1
Oui, a ajouté CoreDate. Mais pas de chance.
Suresh Durishetti
4
Vous avez oublié d'ajouter la sauvegarde d'appel sur le contexte, ajoutez context.save () et vous êtes
prêt
Oui, cela nécessite de sauvegarder le contexte sinon aucun changement ne se produira
Surendra Kumar
5

Swift 3.X et Swift 4.X , moyen facile. Modifier uniquement YourTable

    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)")
    }
SwiftDeveloper
la source
Vous pouvez également utiliser cette construction: let fetchRequest: NSFetchRequest <NSFetchRequestResult> = YourTable.fetchRequest ()
Daniil Chuiko
5

iOS 10 et versions ultérieures

Fonctionne avec toutes les versions. Passez le nom de l'entité et parcourez pour supprimer toutes les entrées et enregistrer 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)")
        }
    }
Karun Kumar
la source
2
Merci d'avoir posté votre réponse. Ça marche pour moi. Mais vous ne devez pas simplement copier et coller votre code ici. Pour une newbee on ne sait pas ce que vos CoreDataStack()ou DataController()classes sont. Une mise à jour serait appréciée;)
Nico S.
4

Prolonger la réponse de Dave Delong.

Version Swift qui prend également en charge iOS 9 et les versions précédentes. J'ai également couvert la gestion des erreurs dans ceci:

laissez appDelegate: AppDelegate = UIApplication.sharedApplication (). delegate as! AppDelegate

    let fetchRequest = NSFetchRequest(entityName: "Car")
    if #available(iOS 9.0, *) {
        let delete = NSBatchDeleteRequest(fetchRequest: fetchRequest)
        do {
            try appDelegate.persistentStoreCoordinator.executeRequest(delete, withContext: appDelegate.managedObjectContext)
        } catch let error as NSError {
            print("Error occured while deleting: \(error)")
        }
    } else {
        // Fallback on earlier versions
        let carRequest = NSFetchRequest()
        carRequest.entity = NSEntityDescription.entityForName("Cars", inManagedObjectContext: appDelegate.managedObjectContext)
        carRequest.includesPropertyValues = false

        do {
            let cars: NSArray = try appDelegate.managedObjectContext.executeFetchRequest(carRequest)

            for car in cars {
                appDelegate.managedObjectContext.delete(car)
            }

            try appDelegate.managedObjectContext.save()

        } catch let error as NSError {
            print("Error occured while fetching or saving: \(error)")
        }
    }
Maheen Khalid
la source
voté. La façon dont ios 9 de supprimer les enregistrements est vraiment awsm.
Shobhakar Tiwari
2

Pourquoi ne pas intégrer les données que vous recevez avec le cache existant? Sinon, ce n'est pas vraiment «rafraîchissant», c'est «recommencer» et vous pouvez aussi bien supprimer / supprimer le fichier SQLLite et recommencer (en supposant que vous ne persistez pas d'autres données également).

AlBlue
la source
1
Mauvaise solution. S'il y a d'autres tables dans la base de données Sqlite, nous perdrons évidemment tout cela. C'est plus un hack pour une solution particulière et ne peut pas être considéré pour les cas plus importants.
Deepak GM
2

Swift 4,
fonction statique iOS 10+ qui peut demander à toute entité de supprimer toutes ses données

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

«Chambre» est une entité

Room.removeAllObjectsInContext(self.persistentContainer.viewContext)

Modifiée le 20191025: l'instruction "Self.fetchRequest ()" peut provoquer un problème si nous utilisons plusieurs cibles dans les mêmes projets. Donc remplacé par NSFetchRequest (entityName: String (décrivant: self))

jpulikkottil
la source
1

si l'entité contient beaucoup d'entrées, la meilleure façon est la suivante car elle économise de la mémoire

 - (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];
    }
}
fièvre poyo.
la source
1

Dans Swift 3.0

 func deleteAllRecords() {
        //delete all data
        let context = appDelegate.persistentContainer.viewContext

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

        do {
            try context.execute(deleteRequest)
            try context.save()
        } catch {
            print ("There was an error")
        }
    }
Amul4608
la source
1

Ce code fonctionnera pour iOS 9 et versions antérieures

class func deleteAllRecords(in entity : String) // entity = Your_Entity_Name
    {

        let context = CoreDataStack.getContext() // Note:- Replace your context here with CoreDataStack.getContext()
        let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
        if #available(iOS 9, *)
        {
            let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
            do
            {
                try context.execute(deleteRequest)
                try context.save()
            }
            catch
            {
                print("There was an error:\(error)")
            }
        }
        else
        {
            do{
                let deleteRequest = try context.fetch(deleteFetch)
                for anItem in deleteRequest {
                    context.delete(anItem as! NSManagedObject)
                }
            }
            catch
            {
                print("There was an error:\(error)")
            }
        }
        CoreDataStack.saveContext() // Note:- Replace your savecontext here with CoreDataStack.saveContext()
    }
Varun Naharia
la source
1

iOS 9.0 et versions ultérieures:

NSBatchDeleteRequestest utilisé pour supprimer des enregistrements dans les données de base. Il fonctionne très rapidement et prend moins de temps pour supprimer tous les enregistrements d'une entité. Il faut NSFetchRequesten argument. Si vous souhaitez supprimer tous les enregistrements d'une entité, vous pouvez l'utiliser et cela fonctionne pour moi.

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)
    }
Développeur MARK IOS
la source
1

purge rapide de tous les objets dans DB:

func purgeAllData() {
    let uniqueNames = persistentContainer.managedObjectModel.entities.compactMap({ $0.name })

    uniqueNames.forEach { (name) in
      let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: name)
       let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
         do {
        try persistentContainer.viewContext.execute(batchDeleteRequest)
      } catch {
        let nserror = error as NSError
        fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
      }
   }
 }
gbk
la source
0

La réponse Swift 2.0 de Dave Delongs plantait pour moi (dans iOS 9)

Mais cela a fonctionné:

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

    do {
        try managedObjectContext.executeRequest(deleteRequest)
        try managedObjectContext.save()
    }
    catch let error as NSError {
       // Handle error
    }
lueur
la source
0

Solution Swift 3 avec iOS 9 «NSBatchDeleteRequest» et retour aux versions antérieures d'iOS implémentées en tant qu'extension sur «NSManagedObjectContext». Référence Apple 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) }
            }
        }
    }
}
chriswillow
la source
0

Utilisez NSBatchDeleteRequest pour supprimer plusieurs enregistrements si iOS minimal est 9,0. S'il s'agit d'un thread d'arrière-plan, exécutez NSManagedObjectContext, sinon utilisez NSFetchRequest pour obtenir les enregistrements et supprimez tous les enregistrements de la boucle et Enregistrer une fois la suppression effectuée.

Jeetendra Kumar
la source
0

dans iOS 11.3 et Swift 4.1

let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
        let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest )
        batchDeleteRequest.resultType = .resultTypeCount
        do {
            let batchDeleteResult = try dataController.viewContext.execute(batchDeleteRequest) as! NSBatchDeleteResult
            print("The batch delete request has deleted \(batchDeleteResult.result!) records.")
            dataController.viewContext.reset() // reset managed object context (need it for working)
        } catch {
            let updateError = error as NSError
            print("\(updateError), \(updateError.userInfo)")
        }

vous devez appeler reset après avoir exécuté. Sinon, il ne sera pas mis à jour sur la vue de table.

tien113
la source
0
    func deleteAll(entityName: String) {

    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
    let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
    deleteRequest.resultType = .resultTypeObjectIDs
    guard let context = self.container?.viewContext
        else { print("error in deleteAll")
            return }

    do {
        let result = try context.execute(deleteRequest) as? NSBatchDeleteResult
        let objectIDArray = result?.result as? [NSManagedObjectID]
        let changes: [AnyHashable : Any] = [NSDeletedObjectsKey : objectIDArray as Any]
        NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [context])
    } catch {
        print(error.localizedDescription)
    }
}
Matt Bearson
la source
0

la façon OOP sans aucune chaîne comme noms d'entités Swift 3+, Xcode 10+

func batchDelete<T>(in context: NSManagedObjectContext, fetchRequest: NSFetchRequest<T>) throws {
    guard let request = fetchRequest as? NSFetchRequest<NSFetchRequestResult> else {
        throw ErrorService.defaultError
    }
    let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: request)
    do {
        try context.execute(batchDeleteRequest)
    } catch {
        throw error
    }
}

puis appelez simplement dans le bloc do / catch

    let fetchRequest: NSFetchRequest<YourEntity> = YourEntity.fetchRequest()
    do {
        let data = try context.fetch(fetchRequest)
        if data.count > 0 {
            try self.batchDelete(in: context, fetchRequest: fetchRequest)
        }
    } catch {
        // throw error
    }
Jack Daniel
la source
-1

Dans Swift 2.0:

func deleteAllData(entity: String)
{
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext
    let fetchRequest = NSFetchRequest(entityName: entity)
    fetchRequest.returnsObjectsAsFaults = false

    do 
    {
        let results = try managedContext.executeFetchRequest(fetchRequest)
        for managedObject in results
        {
            let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
            managedContext.deleteObject(managedObjectData)
        }
    } catch let error as NSError {
        print("Detele all data in \(entity) error : \(error) \(error.userInfo)")
    }
}
Rajesh Loganathan
la source