Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Friday, March 4, 2016

Core Data: Quickest way to delete all instances of an entity

Core Data: Quickest way to delete all instances of an entity


I'm using Core Data to locally persist results from a Web Services call. The web service returns the full object model for, let's say, "Cars" - could be about 2000 of them (and I can't make the Web Service return anything less than 1 or ALL cars.

The next time I open my application, I want to refresh the Core Data persisted copy by calling the Web Service for all Cars again, however to prevent duplicates I would need to purge all data in the local cache first.

Is there a quicker way to purge ALL instances of a specific entity in the managed object context (e.g. all entities of type "CAR"), or do I need to query them call, then iterate through the results to delete each, then save?

Ideally I could just say delete all where entity is Blah.

Answer by AlBlue for Core Data: Quickest way to delete all instances of an entity


Why not fold in the data that you receive with the existing cache? Otherwise it's not really 'refreshing', it's 'starting again' and you might as well drop/delete the SQLLite file and start again (assuming you're not persisting other data as well).

Answer by Dave DeLong for Core Data: Quickest way to delete all instances of an entity


iOS 9 and later:

iOS 9 added a new class called NSBatchDeleteRequest that allows you to easily delete objects matching a predicate without having to load them all in to memory. Here's how you'd use it:

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  }  

Objective-C

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Car"];  NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];    NSError *deleteError = nil;  [myPersistentStoreCoordinator executeRequest:delete withContext:myContext error:&deleteError];  

More information about batch deletions can be found in the "What's New in Core Data" session from WWDC 2015 (starting at ~14:10).

iOS 8 and earlier:

Fetch 'em all and delete 'em all:

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  

Answer by T. Markle for Core Data: Quickest way to delete all instances of an entity


This is a similar question to the one here and someone suggested setting up a relationship delete rule so you only have to delete one object. So if you have or can make an entity with a to-many relationship to the cars and set the delete rule to cascade when you delete the higher entity all the cars will be deleted as well. This may save some processing time since you don't have to do the steps involved with loading ALL the cars. In a larger data set this could be absolutely necessary.

Answer by Numereyes for Core Data: Quickest way to delete all instances of an entity


A little bit more cleaned and universal : Add this method :

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

Answer by Mr Q.C. for Core Data: Quickest way to delete all instances of an entity


A good answer was already posted, this is only a recommendation!

A good way would be to just add a category to NSManagedObject and implement a method like I did:

Header File (e.g. NSManagedObject+Ext.h)

@interface NSManagedObject (Logic)    + (void) deleteAllFromEntity:(NSString*) entityName;    @end  

Code File: (e.g. 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  

... the only thing you have to is to get the managedObjectContext from the app delegate, or where every you have it in ;)

afterwards you can use it like:

[NSManagedObject deleteAllFromEntity:@"EntityName"];  

one further optimization could be that you remove the parameter for tha entityname and get the name instead from the clazzname. this would lead to the usage:

[ClazzName deleteAllFromEntity];  

Answer by poyo fever. for Core Data: Quickest way to delete all instances of an entity


if the entity contains a lot of entries the best way is like this because it saves memory

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

Answer by Ixx for Core Data: Quickest way to delete all instances of an entity


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

Answer by Gaurav Sharma for Core Data: Quickest way to delete all instances of an entity


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

Answer by Maheen Khalid for Core Data: Quickest way to delete all instances of an entity


Extending Dave Delong's answer.

Swift Version that takes care of iOS 9 and previous versions as well. I have also covered Error handling in this:

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

Answer by g_low for Core Data: Quickest way to delete all instances of an entity


Dave Delongs's Swift 2.0 answer was crashing for me (in iOS 9)

But this worked:

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      }  


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.