ข้อมูลหลัก: วิธีที่รวดเร็วที่สุดในการลบอินสแตนซ์ทั้งหมดของเอนทิตี


383

ฉันใช้ Core Data เพื่อยืนยันผลการโทรจากเว็บเซอร์วิส บริการบนเว็บส่งคืนโมเดลวัตถุแบบเต็มสำหรับสมมติว่า "Cars" - อาจเป็นประมาณ 2000 รายการ (และฉันไม่สามารถทำให้ Web Service ส่งคืนสิ่งใดก็ตามที่น้อยกว่า 1 คันหรือทั้งหมด

ในครั้งต่อไปที่ฉันเปิดแอปพลิเคชันของฉันฉันต้องการรีเฟรช Core Data ที่ยังคงมีอยู่โดยเรียกใช้ Web Service สำหรับรถยนต์ทุกคันอีกครั้งอย่างไรก็ตามเพื่อป้องกันการซ้ำซ้อนฉันจะต้องล้างข้อมูลทั้งหมดในแคชในเครื่องก่อน

มีวิธีที่รวดเร็วกว่าในการกำจัดทุกอินสแตนซ์ของเอนทิตีเฉพาะในบริบทวัตถุที่มีการจัดการ (เช่นเอนทิตีทั้งหมดของประเภท "CAR") หรือฉันต้องค้นหาพวกเขาโทรแล้ววนซ้ำผ่านผลลัพธ์เพื่อลบแต่ละรายการจากนั้นบันทึก?

เป็นการดีที่ฉันจะพูดลบทั้งหมดที่เอนทิตี้ของ Blah


คุณสามารถใช้ฐานข้อมูลในหน่วยความจำ
J. Doe

คำตอบ:


718

iOS 9 และใหม่กว่า:

iOS 9 เพิ่มคลาสใหม่ที่เรียกNSBatchDeleteRequestว่าช่วยให้คุณสามารถลบวัตถุที่ตรงกับเพรดิเคตได้อย่างง่ายดายโดยไม่ต้องโหลดทั้งหมดลงในหน่วยความจำ นี่คือวิธีที่คุณจะใช้:

สวิฟท์ 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
}

Objective-C

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

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

ข้อมูลเพิ่มเติมเกี่ยวกับการลบแบทช์สามารถพบได้ในเซสชั่น "มีอะไรใหม่ในแกนข้อมูล" จาก WWDC 2015 (เริ่มต้นที่ ~ 14: 10)

iOS 8 และรุ่นก่อนหน้า:

ดึง 'em all และลบ' em ทั้งหมด:

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

74
ฉันจะกำหนดค่าการดึงข้อมูลเพื่อดึงข้อมูล NSManagedObjectID เท่านั้นเพื่อลดค่าใช้จ่ายใด ๆ จากการโหลดในโครงสร้างวัตถุแบบเต็ม
Marcus S. Zarra

38
ไม่ชัดเจนว่าจะดึงข้อมูลเฉพาะ NSMangagedObjectID .. ใช้ [allCars setIncludesPropertyValues: NO] ได้อย่างไร (และไม่ต้องไปหาวิธีทำ NSPropertyDescription สำหรับ object ID!)
ohhorob

6
ขออภัยสำหรับคำถามที่สมัครใหม่: คุณต้องการบันทึกบริบทหลังจากสิ้นสุดการวนรอบหรือไม่ เช่น [บันทึก myContext];
Steve

6
มีสิ่งอำนวยความสะดวกใหม่ใน Core Data เพื่อให้มีประสิทธิภาพมากขึ้นหรือไม่ นี่เป็นปัญหาที่ร้ายแรงสำหรับแอพของฉันที่ไกลไปตามถนนที่นำไปสู่ ​​Core Data ใช้เวลาหลายวินาทีในการลบ 4000 รายการทั้งหมดจากเพียงหนึ่งในหลาย ๆ ตาราง ผู้ใช้รอนานเกินไป คำขอเดียวกันโดยตรงกับ sqlite ดูเหมือนทันที
David

4
@DaveDeLong วิธี NSBatchDeleteRequest สามารถทริกเกอร์ผู้มอบหมาย NSFetchedResultsController ได้อย่างไร ฉันลองเกือบทุกอย่าง แต่ไม่มีอะไรเกิดขึ้น
Foriger

36

รีเซ็ตเอนทิตีใน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")
        }
    }

32

เพิ่มความสะอาดและเป็นสากลขึ้นเล็กน้อย: เพิ่มวิธีนี้:

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

16

สำหรับ 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")
  }
}

12

สวิฟท์:

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

1
คำตอบนี้ควรได้รับการอัปเดตด้วยการจัดการข้อผิดพลาดในการลอง / จับใหม่
Suragch

10

นี่เป็นคำถามที่คล้ายกับคำถามที่นี่และมีคนแนะนำให้ตั้งค่ากฎการลบความสัมพันธ์ดังนั้นคุณจะต้องลบวัตถุหนึ่งรายการเท่านั้น ดังนั้นหากคุณมีหรือสามารถสร้างเอนทิตีที่มีความสัมพันธ์กับรถยนต์จำนวนมากและตั้งค่ากฎการลบเป็นแบบเรียงซ้อนเมื่อคุณลบเอนทิตีที่สูงกว่ารถยนต์ทั้งหมดจะถูกลบเช่นกัน วิธีนี้อาจช่วยประหยัดเวลาในการประมวลผลเนื่องจากคุณไม่ต้องทำตามขั้นตอนที่เกี่ยวข้องกับการโหลดรถยนต์ทั้งหมด ในชุดข้อมูลที่ใหญ่กว่านี้อาจจำเป็นอย่างยิ่ง


1
ฉันเพิ่งลองสิ่งนี้ในโครงการปัจจุบันของฉันด้วยวัตถุข้อมูลหลัก 600 ตัว เมื่อฉันห่อหุ้มพวกเขาในวัตถุอื่นด้วยน้ำตกมันใช้เวลาประมาณ 9.1 วินาทีในการลบ ถ้าฉันใช้วิธีที่เดฟแนะนำเกี่ยวกับมันใช้เวลาประมาณ 8.7 วินาทีในการลบ ไม่แตกต่างที่โดดเด่นสำหรับฉัน
Andrew Zimmer

8

คำตอบที่ดีถูกโพสต์แล้วนี่เป็นเพียงคำแนะนำ!

วิธีที่ดีคือเพิ่มหมวดหมู่NSManagedObjectและใช้วิธีการเช่นเดียวกับที่ฉันทำ:

ไฟล์ส่วนหัว (เช่นNSManagedObject+Ext.h)

@interface NSManagedObject (Logic)

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

@end

รหัสไฟล์: (เช่น 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

... สิ่งเดียวที่คุณต้องมีคือการได้รับการจัดการ ObjectContext จากตัวแทนแอพหรือที่ที่คุณมีทุกอย่างในนั้น;)

หลังจากนั้นคุณสามารถใช้งานได้เช่น:

[NSManagedObject deleteAllFromEntity:@"EntityName"];

การปรับให้เหมาะสมอีกอย่างหนึ่งอาจเป็นได้ว่าคุณลบพารามิเตอร์สำหรับ tha entityname และรับชื่อแทนจาก clazzname สิ่งนี้จะนำไปสู่การใช้งาน:

[ClazzName deleteAllFromEntity];

impl ที่สะอาดมากขึ้น (เป็นหมวดหมู่ของ 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

การใช้งานแล้ว:

[managedObjectContext deleteAllFromEntity:@"EntityName"];

1
ขออภัย[AppDelegate managedObjectContext]ไม่จำเป็นต้องเป็น "สถาปัตยกรรมสะอาด" .. ;-)
Daniel Rinser

ตกลงจริง รหัสข้างต้นอ้างอิงตาม managedObjectContext หนึ่งรายการ หลักแรก;) ในรหัสแบบมัลติเธรดฉันมักจะรวมกระทรวง
การคลัง

1
@DanielRinser สามารถdeleteAllFromEntity: inManagedObjectContext:
Mohamed Elkassas

ใช่. ดีกว่าจะเปลี่ยนเมธอด deleteAllFromEntity จากเมธอดคลาสเป็นเมธอดอ็อบเจ็กต์ จากนั้นคุณสามารถเรียกใช้ deleteAllFromEntity โดยตรงบนอินสแตนซ์ MOC
ศูนย์ Dinhobl

7

อัพเดต Swift 4, iOS 12 และ Xcode 10

ทำงานและตัดได้ 100%

เพียงแค่วางฟังก์ชั่นนี้ในคลาสที่เกี่ยวข้องและเรียกใช้ฟังก์ชั่นนี้self.deleteData()ในviewDidLoad()หรือที่ใดก็ได้หรือภายใต้ฟังก์ชั่นหรือปุ่มเพื่อให้ลบข้อมูลทั้งหมดจากเอนทิตีและแทนที่ "myEntity" เป็นเอนทิตีของคุณ ข้อมูลหลัก

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

ขอบคุณ แต่ทำไมแนวคิด NSBatchDeleteRequest ไม่ทำงาน? ความคิดใด ๆ
Suresh Durishetti

@SureshDurishetti คุณนำเข้า CoreData ในชั้นเรียนของคุณหรือไม่
Xcodian Solangi

1
ใช่เพิ่ม CoreDate แต่ไม่มีโชค
Suresh Durishetti

4
คุณลืมที่จะเพิ่มการเรียกประหยัดกับบริบทเพิ่ม context.save () และคุณความดีกำลังจะไป
Parama Dharmika

ใช่สิ่งนี้จำเป็นต้องบันทึกบริบทมิฉะนั้นจะไม่มีการเปลี่ยนแปลงเกิดขึ้น
Surendra Kumar

5

Swift 3.XและSwift 4.Xวิธีง่ายๆ เปลี่ยน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)")
    }

นอกจากนี้คุณสามารถใช้โครงสร้างนี้: let fetchRequest: NSFetchRequest <NSFetchRequestResult> = YourTable.fetchRequest ()
Daniil Chuiko

5

iOS 10 และใหม่กว่า

ใช้ได้กับทุกรุ่น ส่งชื่อเอนทิตีและวนซ้ำเพื่อลบรายการทั้งหมดและบันทึกบริบท

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

2
ขอบคุณสำหรับการโพสต์คำตอบของคุณ ที่เหมาะกับฉัน แต่คุณไม่ควรคัดลอกและวางรหัสของคุณที่นี่ สำหรับ newbee มันไม่ชัดเจนว่าคุณCoreDataStack()หรือDataController()ชั้นเรียนคืออะไร การปรับปรุงจะได้รับการชื่นชม;)
Nico S.

4

การขยายคำตอบของ Dave Delong

Swift Version ที่ดูแล iOS 9 และเวอร์ชั่นก่อนหน้าเช่นกัน ฉันได้กล่าวถึงข้อผิดพลาดในการจัดการนี้:

ให้ appDelegate: AppDelegate = UIApplication.sharedApplication (). มอบสิทธิ์เป็น! 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)")
        }
    }

upvoted iOS 9 วิธีการลบบันทึกเป็น awsm จริงๆ
Shobhakar Tiwari

2

ทำไมไม่พับข้อมูลที่คุณได้รับด้วยแคชที่มีอยู่? มิฉะนั้นมันจะไม่ 'รีเฟรช' จริงๆมันคือ 'เริ่มใหม่อีกครั้ง' และคุณอาจปล่อย / ลบไฟล์ SQLLite และเริ่มใหม่อีกครั้ง (สมมติว่าคุณไม่ได้เก็บข้อมูลอื่นไว้เช่นกัน)


1
ทางออกที่ไม่ดี หากมีตารางอื่น ๆ ในฐานข้อมูล Sqlite เราจะปล่อยทุกอย่างที่เห็นได้ชัด นี่เป็นแฮ็คเพิ่มเติมสำหรับโซลูชันเฉพาะและไม่สามารถพิจารณาได้ในกรณีที่มีขนาดใหญ่กว่า
Deepak GM

2


ฟังก์ชั่นSwift 4, iOS 10+ซึ่งสามารถนำไปใช้กับเอนทิตีใด ๆ เพื่อลบข้อมูลทั้งหมด

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

'ห้อง' เป็นนิติบุคคล

Room.removeAllObjectsInContext(self.persistentContainer.viewContext)

แก้ไขเมื่อ 20191025: คำสั่ง "Self.fetchRequest ()" อาจทำให้เกิดปัญหาหากเราใช้หลายเป้าหมายในโครงการเดียวกัน ดังนั้นแทนที่ด้วย NSFetchRequest (entityName: String (อธิบาย: self))


1

ถ้าเอนทิตีมีรายการจำนวนมากวิธีที่ดีที่สุดก็คือเช่นนี้เพราะมันช่วยประหยัดหน่วยความจำ

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

1

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

1

รหัสนี้จะใช้ได้กับทั้ง iOS 9 และต่ำกว่า

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

1

iOS 9.0 และใหม่กว่า:

NSBatchDeleteRequestใช้เพื่อลบบันทึกในข้อมูลหลัก ทำงานได้อย่างรวดเร็วและใช้เวลาน้อยลงในการลบระเบียนทั้งหมดออกจากเอนทิตี มันต้องมีการNSFetchRequestโต้แย้ง หากคุณต้องการลบระเบียนทั้งหมดจากเอนทิตีคุณสามารถใช้มันและมันทำงานได้สำหรับฉัน

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

1

กำจัดวัตถุทั้งหมดในฐานข้อมูลอย่างรวดเร็ว:

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

0

คำตอบ Swift 2.0 ของ Dave Delongs ล้มเหลวสำหรับฉัน (ใน iOS 9)

แต่สิ่งนี้ได้ผล:

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
    }

0

โซลูชัน Swift 3 พร้อม iOS 9 'NSBatchDeleteRequest' และย้อนกลับไปใช้ iOS เวอร์ชันก่อนหน้านี้ซึ่งใช้เป็นส่วนขยายใน 'NSManagedObjectContext' การอ้างอิงของ 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) }
            }
        }
    }
}

0

ใช้ NSBatchDeleteRequest เพื่อลบหลายระเบียนถ้า iOS ขั้นต่ำคือ 9.0 หากเธรดพื้นหลังให้เรียกใช้ NSManagedObjectContext save ใช้ NSFetchRequest เพื่อรับเร็กคอร์ดและลบเร็กคอร์ดทั้งหมดในลูปและบันทึกเมื่อทำการลบเสร็จแล้ว


0

ใน iOS 11.3 และ 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)")
        }

คุณต้องโทรใหม่หลังจากที่คุณดำเนินการ มิฉะนั้นจะไม่อัปเดตในมุมมองตาราง


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

0

วิธี OOP โดยไม่ต้องมีสตริงใด ๆ เป็นชื่อเอนทิตี 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
    }
}

จากนั้นเพียงโทรเข้าใน do / catch block

    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
    }

-1

ใน 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)")
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.