ios - telecharger - une erreur est survenue lors de l installation




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

J'utilise des données de base pour persister localement les résultats d'un appel de services Web. Le service Web renvoie le modèle d'objet complet pour, disons, "Cars" - peut-être environ 2000 d'entre eux (et je ne peux pas rendre 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. Cependant, pour éviter les doublons, je dois 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, puis parcourir les résultats pour les supprimer?

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


iOS 9 et plus tard:

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 vous l'utiliseriez:

Swift 2

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

do {
    try myPersistentStoreCoordinator.executeRequest(deleteRequest, withContext: 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 (commençant à ~ 14: 10).

iOS 8 et plus tôt:

Allez les chercher 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

Ceci est une question similaire à celle- here et quelqu'un a suggéré de mettre en place une règle de suppression de relation de sorte que vous ne devez supprimer qu'un seul objet. Donc, si vous avez ou pouvez créer une entité avec une relation to-many aux 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 puisque vous n'avez pas à faire les étapes nécessaires au chargement de TOUTES les voitures. Dans un ensemble de données plus important, cela pourrait être absolument nécessaire.


La réponse de Swift 2.0 de Dave Delongs s'est écrasée 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
    }

Pourquoi ne pas plier les données que vous recevez avec le cache existant? Sinon, ce n'est pas vraiment «rafraichissant», c'est «recommencer» et vous pourriez aussi bien supprimer / supprimer le fichier SQLLite et recommencer (en supposant que vous ne perdiez pas d'autres données).


Swift 3 solution avec iOS 9 'NSBatchDeleteRequest' et le repli vers les versions antérieures de iOS mis en œuvre 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) }
            }
        }
    }
}

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

Utilisez NSBatchDeleteRequest pour supprimer plusieurs enregistrements Si iOS minimum est 9.0. Si le thread d'arrière-plan, exécutez NSManagedObjectContext save else, utilisez NSFetchRequest pour obtenir les enregistrements et supprimer tous les enregistrements dans la boucle for et Enregistrer une fois la suppression effectuée.


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 réinitialiser après l'exécution. Sinon, il ne sera pas mis à jour sur la vue de la table.


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

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

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

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

Swift 4, iOS 10+
Fonction statique qui peut s'appliquer à toute 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 = Self.fetchRequest()
        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)
        }
    }
}

'Room' est une entité

Room.removeAllObjectsInContext(self.persistentContainer.viewContext)

iOS 10 et plus tard

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) ->()) {
        var context = NSManagedObjectContext()
        if #available(iOS 10.0, *) {
            context = your managedObjectContext
        } else {
            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)")
        }
    }




core-data