ios - eliminar - no puedo borrar una app de mi ipad
Datos básicos: la forma más rápida de eliminar todas las instancias de una entidad (22)
iOS 9 y posteriores:
iOS 9 agregó una nueva clase llamada NSBatchDeleteRequest
que le permite eliminar fácilmente los objetos que coinciden con un predicado sin tener que cargarlos todos en la memoria. Así es como lo usarías:
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
}
C objetivo
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Car"];
NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
NSError *deleteError = nil;
[myPersistentStoreCoordinator executeRequest:delete withContext:myContext error:&deleteError];
Puede encontrar más información sobre las eliminaciones por lotes en la sesión "Novedades en los datos básicos" de WWDC 2015 (que comienza en ~ 14: 10).
iOS 8 y anteriores:
Fetch ''em all y eliminar'' 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
Estoy usando Core Data para persistir localmente los resultados de una llamada de servicios web. El servicio web devuelve el modelo de objeto completo para, digamos, "Cars"; podría ser aproximadamente 2000 de ellos (y no puedo hacer que el Servicio Web devuelva nada menos que 1 o TODOS los autos.
La próxima vez que abra mi aplicación, quiero actualizar la copia persistente de Core Data llamando de nuevo al Servicio Web para todos los Autos, sin embargo, para evitar duplicados, primero tendría que limpiar todos los datos en el caché local.
¿Existe una forma más rápida de purgar TODAS las instancias de una entidad específica en el contexto del objeto administrado (por ejemplo, todas las entidades del tipo "CAR"), o debo consultarlas, luego iterar a través de los resultados para eliminarlas y luego guardarlas?
Lo ideal sería decir simplemente borrar todo donde entidad es Blah.
¿Por qué no plegar los datos que recibe con el caché existente? De lo contrario, en realidad no es ''refrescante'', está ''empezando de nuevo'' y es mejor que suelte / elimine el archivo SQLLite y comience de nuevo (suponiendo que no esté conservando otros datos).
Esta es una pregunta similar a la de here y alguien sugirió configurar una regla de eliminación de relación para que solo tenga que eliminar un objeto. Por lo tanto, si tiene o puede hacer que una entidad tenga una relación de muchos con los automóviles y establezca la regla de eliminación en cascada cuando elimine la entidad superior, todos los automóviles también se eliminarán. Esto puede ahorrar algo de tiempo de procesamiento ya que no tiene que realizar los pasos necesarios para cargar TODOS los autos. En un conjunto de datos más grande, esto podría ser absolutamente necesario.
Este código funcionará tanto para iOS 9 como para abajo
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()
}
Extendiendo la respuesta de Dave Delong.
Versión Swift que se ocupa de iOS 9 y versiones anteriores también. También he cubierto el manejo de errores en esto:
deje que 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)")
}
}
La respuesta Swift 2.0 de Dave Delongs se estrelló para mí (en iOS 9)
Pero esto funcionó:
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
}
Restablecer entidad en 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")
}
}
Si la entidad contiene muchas entradas, la mejor manera es así porque ahorra memoria.
- (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];
}
}
Solución Swift 3 con iOS 9 ''NSBatchDeleteRequest'' y respaldo a versiones anteriores de iOS implementadas como una extensión en ''NSManagedObjectContext''. Referencia de 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 poco más limpio y universal: añade este método:
- (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];
}
Una buena respuesta ya fue publicada, esta es solo una recomendación!
Una buena manera sería simplemente agregar una categoría a NSManagedObject
e implementar un método como lo hice:
Archivo de encabezado (por ejemplo, NSManagedObject+Ext.h
)
@interface NSManagedObject (Logic)
+ (void) deleteAllFromEntity:(NSString*) entityName;
@end
Archivo de código: (por ejemplo, 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
... lo único que tienes que hacer es obtener el managedObjectContext del delegado de la aplicación, o donde cada uno lo tiene;)
después puedes usarlo como:
[NSManagedObject deleteAllFromEntity:@"EntityName"];
Una optimización adicional podría ser que elimines el parámetro para el nombre de la entidad y obtengas el nombre del nombre de clave. esto llevaría al uso:
[ClazzName deleteAllFromEntity];
una implementación más limpia (como categoría para 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
El uso entonces:
[managedObjectContext deleteAllFromEntity:@"EntityName"];
Use NSBatchDeleteRequest para eliminar varios registros si el mínimo de iOS es 9.0. Si se trata de un subproceso en segundo plano, ejecute NSManagedObjectContext save; de lo contrario, utilice NSFetchRequest para obtener registros y elimine todos los registros para el bucle for y Save una vez que se elimine.
en iOS 11.3 y 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)")
}
Tienes que reiniciar la llamada después de ejecutar. Si no, no se actualizará en la vista de tabla.
Actualización de Swift 4, iOS 12 y Xcode 10
100% trabajando solo cortar y pegar
Solo pon esta función en clase relevante
y llamar a esta función self.deleteData()
en viewDidLoad()
o en cualquier lugar o debajo de una función o un botón para que al hacer clic en un botón, todos los datos de la entidad se eliminen y reemplacen la "myEntity" como su entidad que ha definido en sus datos centrales
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
{
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)")
}
}
En 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)")
}
}
En 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")
}
}
Para 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")
}
}
Rápido:
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 3.X y Swift 4.X , forma fácil. Cambia solo tu tabla
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)")
}
Swift 4, iOS 10+
Función estática que puede solicitar que cualquier entidad elimine todos sus datos.
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)
}
}
}
''Habitación'' es una entidad
Room.removeAllObjectsInContext(self.persistentContainer.viewContext)
iOS 10 y versiones posteriores
Funciona con todas las versiones. Pase el nombre de la entidad y repítalo para borrar todas las entradas y guardar el contexto.
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)")
}
}
iOS 9.0 y posteriores:
NSBatchDeleteRequest
se utiliza para eliminar registros en datos centrales. Funciona muy rápido y lleva menos tiempo eliminar todos los registros de una entidad. Requiere NSFetchRequest
en el argumento. Si desea eliminar todos los registros de una entidad, puede usarlo y funciona para mí.
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)
}