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

4voto

Maheen Khalid Points 424

Prolongeant la réponse de Dave Delong.

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

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

4voto

jpulikkottil Points 327

Swift 4, iOS 10+
Fonction statique qui peut s'appliquer à n'importe quelle entité pour 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)
        }
    }
}

La "pièce" est une entité

Room.removeAllObjectsInContext(self.persistentContainer.viewContext)

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

4voto

Kirill Points 609

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

2voto

AlBlue Points 7768

Pourquoi ne pas intégrer les données que vous recevez dans le cache existant ? Sinon, ce n'est pas vraiment un "rafraîchissement", c'est un "recommencement" et vous pourriez aussi bien abandonner/supprimer le fichier SQLLite et recommencer (en supposant que vous ne persistez pas d'autres données également).

1 votes

Mauvaise solution. S'il y a d'autres tables dans la base de données Sqlite, nous allons évidemment perdre tout cela. Il s'agit plus d'un hack pour une solution particulière et ne peut être envisagé pour les cas plus importants.

2voto

iOS 9.0 et ultérieur :

NSBatchDeleteRequest est 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 nécessite NSFetchRequest dans l'argumentation. Si vous voulez 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)
    }

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