Kerndaten: Schnellster Weg zum Löschen aller Instanzen einer Entität

383

Ich verwende Core Data, um die Ergebnisse eines Web Services-Aufrufs lokal beizubehalten. Der Webdienst gibt das vollständige Objektmodell für beispielsweise "Autos" zurück - etwa 2000 davon (und ich kann den Webdienst nicht dazu bringen, weniger als 1 oder ALLE Autos zurückzugeben.

Wenn ich meine Anwendung das nächste Mal öffne, möchte ich die Kopie der persistierten Kerndaten aktualisieren, indem ich den Webdienst für alle Fahrzeuge erneut aufrufe. Um jedoch Duplikate zu vermeiden, müsste ich zuerst alle Daten im lokalen Cache löschen.

Gibt es eine schnellere Möglichkeit, ALLE Instanzen einer bestimmten Entität im Kontext des verwalteten Objekts zu löschen (z. B. alle Entitäten vom Typ "CAR"), oder muss ich sie abfragen, dann die Ergebnisse durchlaufen, um sie zu löschen, und dann speichern?

Im Idealfall könnte ich einfach sagen, alle löschen, wo Entität Blah ist.

Adaromas
quelle
Sie könnten eine In-Memory-Datenbank verwenden
J. Doe

Antworten:

718

iOS 9 und höher:

iOS 9 hat eine neue Klasse namens hinzugefügt NSBatchDeleteRequest, mit der Sie Objekte, die einem Prädikat entsprechen, einfach löschen können, ohne sie alle in den Speicher laden zu müssen. So würden Sie es verwenden:

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
}

Ziel c

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Car"];
NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];

NSError *deleteError = nil;
[myPersistentStoreCoordinator executeRequest:delete withContext:myContext error:&deleteError];

Weitere Informationen zum Löschen von Stapeln finden Sie in der Sitzung "Was ist neu in den Kerndaten?" Der WWDC 2015 (ab ca. 14: 10 Uhr ).

iOS 8 und früher:

Holen Sie sie alle und löschen Sie sie alle:

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
quelle
74
Ich würde den Abruf auch so konfigurieren, dass nur die NSManagedObjectID abgerufen wird, um den Overhead beim Laden in die vollständige Objektstruktur zu reduzieren.
Marcus S. Zarra
38
Es ist nicht offensichtlich, wie nur die NSMangagedObjectID abgerufen werden soll. Use [allCars setIncludesPropertyValues: NO]; (Und machen Sie sich nicht die Mühe, nach einer NSPropertyDescription für die Objekt-ID zu
suchen
6
Entschuldigung für die Frage des Neulings: Müssen Sie den Kontext nach dem Ende der for-Schleife speichern? zB [myContext save];
Steve
6
Gibt es eine neue Einrichtung in Core Data, um dies effizienter zu gestalten? Dies ist ein ernstes Problem für meine App, die bereits weit entfernt auf Core Data portiert. Es dauert mehrere Sekunden, um alle 4000 Einträge aus nur einer von mehreren Tabellen zu löschen. Dies ist zu lang, als dass der Benutzer warten könnte. Dieselbe Anfrage direkt mit SQLite scheint augenblicklich.
David
4
@DaveDeLong Wie kann NSBatchDeleteRequest den NSFetchedResultsController-Delegaten auslösen? Ich versuche fast alles, aber nichts passiert.
Foriger
36

Entität in Swift 3 zurücksetzen :

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
quelle
32

Ein bisschen sauberer und universeller: Fügen Sie diese Methode hinzu:

- (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
quelle
16

Für 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
quelle
12

Schnell:

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
quelle
1
Diese Antwort sollte mit der neuen Try / Catch-Fehlerbehandlung aktualisiert werden
Suragch
10

Dies ist eine ähnliche Frage wie hier, und jemand hat vorgeschlagen, eine Regel zum Löschen von Beziehungen einzurichten, sodass Sie nur ein Objekt löschen müssen. Wenn Sie also eine Entität mit einer zu vielen Beziehung zu den Autos haben oder erstellen können und die Löschregel auf Kaskade setzen, wenn Sie die höhere Entität löschen, werden auch alle Autos gelöscht. Dies kann einige Verarbeitungszeit sparen, da Sie nicht die Schritte ausführen müssen, die zum Laden ALLER Autos erforderlich sind. In einem größeren Datensatz kann dies unbedingt erforderlich sein.

T. Markle
quelle
1
Ich habe dies gerade in meinem aktuellen Projekt mit ungefähr 600 Kerndatenobjekten versucht. Als ich sie mit Kaskade in ein anderes Objekt eingekapselt habe, dauerte das Löschen ungefähr 9,1 Sekunden. Wenn ich die von Dave vorgeschlagene Methode verwendet habe, dauert das Löschen ungefähr 8,7 Sekunden. Für mich kein nennenswerter Unterschied.
Andrew Zimmer
8

Eine gute Antwort wurde bereits gepostet, dies ist nur eine Empfehlung!

Ein guter Weg wäre, einfach eine Kategorie hinzuzufügen NSManagedObjectund eine Methode zu implementieren, wie ich es getan habe:

Header-Datei (zB NSManagedObject+Ext.h)

@interface NSManagedObject (Logic)

+ (void) deleteAllFromEntity:(NSString*) entityName;

@end

Codedatei: (zB 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

... das einzige, was Sie tun müssen, ist, den manageObjectContext vom App-Delegaten abzurufen, oder wo jeder, in dem Sie ihn haben;)

danach können Sie es verwenden wie:

[NSManagedObject deleteAllFromEntity:@"EntityName"];

Eine weitere Optimierung könnte darin bestehen, dass Sie den Parameter für den Entitätsnamen entfernen und stattdessen den Namen aus dem Clazznamen abrufen. Dies würde zur Verwendung führen:

[ClazzName deleteAllFromEntity];

ein saubereres Impl (als Kategorie zu 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

Die Verwendung dann:

[managedObjectContext deleteAllFromEntity:@"EntityName"];
Erhard Dinhobl
quelle
1
Sorry, aber es [AppDelegate managedObjectContext]ist nicht unbedingt eine "saubere Architektur" .. ;-)
Daniel Rinser
Ok, stimmt. Der obige Code basiert auf einem ManagedObjectContext. der primäre;) Im Multithread-Code
füge
1
@ DanielRinser kann seindeleteAllFromEntity: inManagedObjectContext:
Mohamed Elkassas
Ja. Besser wäre es, die deleteAllFromEntity-Methode von einer Klassenmethode in eine Objektmethode zu ändern. Anschließend können Sie deleteAllFromEntity direkt auf einer MOC-Instanz aufrufen.
Erhard Dinhobl
7

Swift 4, iOS 12 und Xcode 10 Update

100% arbeiten nur ausschneiden und einfügen

Fügen Sie diese Funktion einfach in die entsprechende Klasse ein und rufen Sie diese Funktion self.deleteData()in viewDidLoad()oder an einer beliebigen Stelle oder unter einer Funktion oder einer Schaltfläche auf, sodass durch Klicken auf eine Schaltfläche alle Daten aus der Entität gelöscht werden sollen, und ersetzen Sie die "myEntity" als Ihre Entität, die Sie in Ihrer definiert haben Kerndatei

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
quelle
Vielen Dank, aber warum funktioniert das NSBatchDeleteRequest-Konzept nicht? irgendeine Idee.
Suresh Durishetti
@SureshDurishetti hast du CoreData in deine Klasse importiert?
Xcodian Solangi
1
Ja, CoreDate hinzugefügt. Aber kein Glück.
Suresh Durishetti
4
Sie haben vergessen, Call Save im Kontext hinzuzufügen, context.save () hinzuzufügen und los geht's
Parama Dharmika
Ja, dies erfordert das Speichern des Kontexts, da sonst keine Änderungen vorgenommen werden
Surendra Kumar,
5

Swift 3.X und Swift 4.X , einfache Möglichkeit. Ändern Sie nur Ihre Tabelle

    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
quelle
Sie können auch diese Konstruktion verwenden: let fetchRequest: NSFetchRequest <NSFetchRequestResult> = YourTable.fetchRequest ()
Daniil Chuiko
5

iOS 10 und höher

Funktioniert mit allen Versionen. Übergeben Sie den Entitätsnamen und durchlaufen Sie ihn, um alle Einträge zu löschen und den Kontext zu speichern.

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
quelle
2
Vielen Dank für Ihre Antwort. Das ist für mich in Ordnung. Sie sollten Ihren Code jedoch nicht einfach hier kopieren und einfügen. Für einen Neuling ist nicht klar, was Ihre CoreDataStack()oder DataController()Klassen sind. Ein Update wäre dankbar;)
Nico S.
4

Erweiterung der Antwort von Dave Delong.

Schnelle Version, die sich auch um iOS 9 und frühere Versionen kümmert. Ich habe auch die Fehlerbehandlung darin behandelt:

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)")
        }
    }
Maheen Khalid
quelle
upvoted. ios 9 Art und Weise, die Datensätze zu löschen, ist wirklich awsm.
Shobhakar Tiwari
2

Warum falten Sie nicht die Daten ein, die Sie mit dem vorhandenen Cache erhalten? Andernfalls wird es nicht wirklich "aktualisiert", sondern "erneut gestartet". Sie können die SQLLite-Datei auch löschen / löschen und erneut starten (vorausgesetzt, Sie behalten nicht auch andere Daten bei).

AlBlue
quelle
1
Schlechte Lösung. Wenn es andere Tabellen in der Sqlite-Datenbank gibt, werden wir das alles offensichtlich verlieren. Dies ist eher ein Hack für eine bestimmte Lösung und kann für größere Fälle nicht berücksichtigt werden.
Deepak GM
2

Swift 4, iOS 10+
Statische Funktion, die für jede Entität gelten kann, um alle ihre Daten zu entfernen

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

'Raum' ist eine Einheit

Room.removeAllObjectsInContext(self.persistentContainer.viewContext)

Bearbeitet am 20191025: Die Anweisung "Self.fetchRequest ()" kann Probleme verursachen, wenn wir mehrere Ziele in denselben Projekten verwenden. Also ersetzt durch NSFetchRequest (entityName: String (Beschreibung: self))

jpulikkottil
quelle
1

Wenn die Entität viele Einträge enthält, ist dies am besten so, da dadurch Speicherplatz gespart wird

 - (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];
    }
}
Poyo-Fieber.
quelle
1

In 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
quelle
1

Dieser Code funktioniert sowohl für iOS 9 als auch darunter

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
quelle
1

iOS 9.0 und höher:

NSBatchDeleteRequestwird verwendet, um Datensätze in Kerndaten zu löschen. Es funktioniert sehr schnell und benötigt weniger Zeit, um alle Datensätze aus einer Entität zu löschen. Es erfordert NSFetchRequestin Argument. Wenn Sie alle Datensätze aus einer Entität löschen möchten, können Sie sie verwenden und es funktioniert für mich.

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)
    }
MARK IOS Entwickler
quelle
1

Schnelle Bereinigung aller Objekte in 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
quelle
0

Dave Delongs 'Swift 2.0-Antwort stürzte für mich ab (in iOS 9)

Aber das hat funktioniert:

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
    }
glühen
quelle
0

Swift 3-Lösung mit iOS 9 'NSBatchDeleteRequest' und Fallback auf frühere iOS-Versionen, die als Erweiterung von 'NSManagedObjectContext' implementiert wurden. Apple-Referenz 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
quelle
0

Verwenden Sie NSBatchDeleteRequest, um mehrere Datensätze zu löschen, wenn iOS mindestens 9.0 ist. Wenn Sie einen Hintergrund-Thread haben, führen Sie NSManagedObjectContext save aus. Andernfalls verwenden Sie NSFetchRequest, um Datensätze abzurufen und alle Datensätze in der for-Schleife zu löschen. Speichern Sie nach dem Löschen.

Jeetendra Kumar
quelle
0

in iOS 11.3 und 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)")
        }

Sie müssen reset aufrufen, nachdem Sie ausgeführt haben. Wenn nicht, wird es in der Tabellenansicht nicht aktualisiert.

tien113
quelle
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
quelle
0

die OOP-Methode ohne Zeichenfolgen als Entitätsnamen 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
    }
}

dann rufe einfach do / catch block auf

    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
quelle
-1

In 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
quelle