Podstawowe dane: najszybszy sposób na usunięcie wszystkich instancji encji

383

Korzystam z danych podstawowych, aby lokalnie utrwalać wyniki połączenia z usługami sieci Web. Usługa internetowa zwraca pełny model obiektowy dla, powiedzmy, „samochodów” - może to być około 2000 z nich (i nie mogę sprawić, aby usługa internetowa zwróciła mniej niż 1 lub WSZYSTKIE samochody.

Następnym razem, gdy otworzę moją aplikację, chcę odświeżyć utrwaloną kopię Core Data przez ponowne wywołanie usługi sieci Web dla wszystkich samochodów, jednak aby uniknąć duplikatów, najpierw muszę wyczyścić wszystkie dane z lokalnej pamięci podręcznej.

Czy istnieje szybszy sposób na wyczyszczenie WSZYSTKICH instancji określonej encji w kontekście obiektu zarządzanego (np. Wszystkich encji typu „CAR”), czy też muszę zapytać je o wywołanie, a następnie iterować wyniki, aby je usunąć, a następnie zapisać?

Idealnie byłoby po prostu powiedzieć „usuń wszystko, gdzie bytem jest Blah.

Gruczolaki
źródło
Możesz użyć bazy danych w pamięci
J. Doe

Odpowiedzi:

718

iOS 9 i nowsze wersje:

iOS 9 dodał nową klasę o nazwie, NSBatchDeleteRequestktóra umożliwia łatwe usuwanie obiektów pasujących do predykatu bez konieczności ładowania ich wszystkich do pamięci. Oto jak z niego skorzystasz:

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

Cel C

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

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

Więcej informacji na temat usuwania partii można znaleźć w sesji „Co nowego w podstawowych danych” z WWDC 2015 (od ~ 14: 10).

iOS 8 i wcześniejsze:

Pobierz je wszystkie i usuń je wszystkie:

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
źródło
74
Skonfigurowałbym również pobieranie, aby pobierało tylko identyfikator NSManagedObjectID, aby zmniejszyć obciążenie związane z ładowaniem w pełnej strukturze obiektu.
Marcus S. Zarra
38
Nie jest oczywiste, jak pobrać tylko NSMangagedObjectID .. use [allCars setIncludesPropertyValues: NO]; (i nie zawracaj sobie głowy szukaniem sposobu, aby zrobić NSPropertyDescription dla identyfikatora obiektu!)
ohhorob
6
przepraszam za pytanie dla początkujących: czy musisz zapisać kontekst po zakończeniu pętli for? np. [myContext save];
Steve
6
Czy jest jakaś nowa funkcja w Bazie Danych, która usprawni to działanie? Jest to poważny problem dla mojej aplikacji, która jest już daleko na drodze do Core Data. Usunięcie wszystkich 4000 wpisów z jednej z kilku tabel zajmuje kilka sekund. To za długo, aby użytkownik mógł poczekać. To samo żądanie bezpośrednio z sqlite wydaje się natychmiastowe.
David
4
@DaveDeLong W jaki sposób NSBatchDeleteRequest może wyzwalać delegowanie NSFetchedResultsController? Próbuję prawie wszystkiego, ale nic się nie dzieje.
Foriger
36

Zresetuj jednostkę w 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")
        }
    }
Roy
źródło
32

Trochę bardziej oczyszczony i uniwersalny: dodaj tę metodę:

- (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
źródło
16

W przypadku 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
źródło
12

Szybki:

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
źródło
1
Ta odpowiedź powinna zostać zaktualizowana o nową obsługę błędów try / catch
Suragch,
10

To jest podobne pytanie do tego tutaj i ktoś zasugerował skonfigurowanie reguły usuwania relacji, więc musisz usunąć tylko jeden obiekt. Więc jeśli masz lub możesz utworzyć byt mający relację wielu do samochodów i ustaw regułę kasowania kaskadowo, gdy usuniesz wyższy byt, wszystkie samochody również zostaną usunięte. Może to zaoszczędzić trochę czasu na przetwarzanie, ponieważ nie musisz wykonywać czynności związanych z ładowaniem WSZYSTKICH samochodów. W większym zestawie danych może to być absolutnie konieczne.

T. Markle
źródło
1
Właśnie wypróbowałem to w moim obecnym projekcie z około 600 podstawowymi obiektami danych. Gdy zamknąłem je kaskadowo w innym obiekcie, usunięcie trwało około 9,1 sekundy. Jeśli użyłem metody sugerowanej przez Dave'a, usunięcie zajmie około 8,7 sekundy. Nie zauważalna dla mnie różnica.
Andrew Zimmer
8

Dobra odpowiedź została już opublikowana, to tylko rekomendacja!

Dobrym sposobem byłoby po prostu dodanie kategorii NSManagedObjecti wdrożenie metody takiej jak ja:

Plik nagłówka (np. NSManagedObject+Ext.h)

@interface NSManagedObject (Logic)

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

@end

Plik kodu: (np. 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

... jedyne, co musisz zrobić, to pobrać manageObjectContext od delegata aplikacji lub tam, gdzie każdy go ma;)

potem możesz go używać w następujący sposób:

[NSManagedObject deleteAllFromEntity:@"EntityName"];

jedną dalszą optymalizacją może być usunięcie parametru dla nazwy encji i zamiast tego pobranie nazwy z nazwy clazzname. doprowadziłoby to do użycia:

[ClazzName deleteAllFromEntity];

bardziej czysty impl (jako kategoria do 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

Zastosowanie wtedy:

[managedObjectContext deleteAllFromEntity:@"EntityName"];
Erhard Dinhobl
źródło
1
Przepraszamy, ale [AppDelegate managedObjectContext]niekoniecznie jest to „czysta architektura” .. ;-)
Daniel Rinser
OK, prawda Powyższy kod jest oparty na jednym manageObjectContext. pierwszy;) W kodzie wielowątkowym normalnie łączę główny MOC delegata aplikacji z innymi
Erhard Dinhobl
1
@DanielRinser może byćdeleteAllFromEntity: inManagedObjectContext:
Mohamed Elkassas
Tak. Lepiej byłoby zmienić metodę deleteAllFromEntity z metody klasy na metodę obiektową. następnie możesz wywołać metodę deleteAllFromEntity bezpośrednio w instancji MOC.
Erhard Dinhobl
7

Aktualizacja Swift 4, iOS 12 i Xcode 10

W 100% działa tylko wyciąć i wkleić

Wystarczy umieścić tę funkcję w odpowiedniej klasie i wywołać tę funkcję self.deleteData()w viewDidLoad()dowolnym miejscu lub pod funkcją lub przyciskiem, aby po kliknięciu przycisku wszystkie dane z encji mogły zostać usunięte i zastąpić „myEntity” jako encję zdefiniowaną w podstawowe dane

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
źródło
Dziękujemy, ale dlaczego koncepcja NSBatchDeleteRequest nie działa? dowolny pomysł.
Suresh Durishetti
@SureshDurishetti zaimportowałeś CoreData do swojej klasy?
Xcodian Solangi
1
Tak, dodano CoreDate. Ale bez powodzenia.
Suresh Durishetti
4
Zapomniałeś dodać save call w kontekście, dodać context.save () i możesz już iść
Parama Dharmika 30.03.18
Tak, wymaga to zapisania kontekstu, w przeciwnym razie nie nastąpi zmiana
Surendra Kumar,
5

Swift 3.X i Swift 4.X , Łatwy sposób. Zmień tylko YourTable

    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
źródło
Możesz także użyć tej konstrukcji: let fetchRequest: NSFetchRequest <NSFetchRequestResult> = YourTable.fetchRequest ()
Daniil
5

iOS 10 i nowszy

Działa ze wszystkimi wersjami. Przekaż nazwę encji i iteruj, aby usunąć wszystkie wpisy i zapisać kontekst.

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
źródło
2
Dziękujemy za opublikowanie odpowiedzi. To działa dla mnie. Ale nie powinieneś po prostu kopiować i wklejać tutaj swojego kodu. Dla newbee nie jest jasne, co się CoreDataStack()lub DataController()zajęcia są. Aktualizacja byłaby mile widziana;)
Nico S.
4

Rozszerzając odpowiedź Dave'a Delonga.

Szybka wersja, która dba również o iOS 9 i poprzednie wersje. Omówiłem także obsługę błędów w tym:

let appDelegate: AppDelegate = UIApplication.sharedApplication (). deleguj jako! 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
źródło
pozytywnie oceniany. ios 9 sposób usuwania zapisów jest naprawdę świetny.
Shobhakar Tiwari
2

Dlaczego nie złożyć danych, które otrzymujesz z istniejącą pamięcią podręczną? W przeciwnym razie nie jest to tak naprawdę „odświeżanie”, ale „zaczyna się od nowa” i równie dobrze możesz upuścić / usunąć plik SQLLite i zacząć od nowa (zakładając, że nie utrwalasz również innych danych).

AlBlue
źródło
1
Złe rozwiązanie. Jeśli w bazie danych Sqlite znajdują się inne tabele, oczywiście to wszystko stracimy. Jest to bardziej hack dla konkretnego rozwiązania i nie można go rozpatrywać w większych przypadkach.
Deepak GM,
2

Swift 4, iOS 10+
Funkcja statyczna, którą można zastosować do dowolnego podmiotu w celu usunięcia wszystkich jego danych

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

„Pokój” jest bytem

Room.removeAllObjectsInContext(self.persistentContainer.viewContext)

Edytowane w 20191025: instrukcja „Self.fetchRequest ()” może powodować problemy, jeśli używamy wielu celów w tych samych projektach. Tak zastąpiony przez NSFetchRequest (entityName: String (opisujący: self))

jpulikkottil
źródło
1

jeśli jednostka zawiera wiele wpisów, najlepszym sposobem jest to, ponieważ oszczędza pamięć

 - (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];
    }
}
gorączka poyo.
źródło
1

W 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
źródło
1

Ten kod będzie działał na iOS 9 i niższych

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
źródło
1

iOS 9.0 i nowsze:

NSBatchDeleteRequestsłuży do usuwania rekordów w podstawowych danych. Działa bardzo szybko i usuwanie wszystkich rekordów z encji zajmuje mniej czasu. To wymaga NSFetchRequestkłótni. Jeśli chcesz usunąć wszystkie rekordy z encji, możesz z nich skorzystać i to działa dla mnie.

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 Developer
źródło
1

szybkie czyszczenie wszystkich obiektów w 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
źródło
0

Odpowiedź Swift 2.0 autorstwa Dave'a Delongsa była dla mnie awarią (w iOS 9)

Ale to zadziałało:

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
    }
poświata
źródło
0

Rozwiązanie Swift 3 z iOS 9 „NSBatchDeleteRequest” i powrót do wcześniejszych wersji iOS zaimplementowanych jako rozszerzenie „NSManagedObjectContext”. Referencje 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) }
            }
        }
    }
}
chriswillow
źródło
0

Użyj NSBatchDeleteRequest, aby usunąć wiele rekordów, jeśli minimum iOS to 9.0. Jeśli wątek w tle, wykonaj NSManagedObjectContext zapisz, użyj NSFetchRequest, aby pobrać rekordy i usunąć wszystkie rekordy w pętli for i zapisz po usunięciu.

Jeetendra Kumar
źródło
0

w iOS 11.3 i 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)")
        }

musisz wykonać reset po zakończeniu. Jeśli nie, nie zostanie zaktualizowany w widoku tabeli.

tien113
źródło
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
źródło
0

sposób OOP bez żadnych ciągów nazw podmiotów 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
    }
}

następnie wystarczy wywołać blok do / catch

    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
źródło
-1

W 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
źródło