คุณรู้วิธีการลบรายการทั้งหมดที่เก็บไว้ใน Core Data หรือไม่? สคีมาของฉันควรคงเดิม ฉันต้องการรีเซ็ตเป็นค่าว่าง
แก้ไข
ฉันต้องการทำสิ่งนี้โดยทางโปรแกรมเพื่อให้ผู้ใช้สามารถกดreset
ปุ่มได้
คุณรู้วิธีการลบรายการทั้งหมดที่เก็บไว้ใน Core Data หรือไม่? สคีมาของฉันควรคงเดิม ฉันต้องการรีเซ็ตเป็นค่าว่าง
แก้ไข
ฉันต้องการทำสิ่งนี้โดยทางโปรแกรมเพื่อให้ผู้ใช้สามารถกดreset
ปุ่มได้
คำตอบ:
คุณยังสามารถลบไฟล์โดยทางโปรแกรมโดยใช้วิธี NSFileManager: removeItemAtPath ::
NSPersistentStore *store = ...;
NSError *error;
NSURL *storeURL = store.URL;
NSPersistentStoreCoordinator *storeCoordinator = ...;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
จากนั้นเพียงเพิ่มที่เก็บถาวรกลับเพื่อให้แน่ใจว่าได้สร้างใหม่อย่างถูกต้อง
วิธีการเขียนโปรแกรมสำหรับการวนซ้ำผ่านแต่ละเอนทิตีนั้นช้าลงและมีแนวโน้มที่จะเกิดข้อผิดพลาด การใช้สำหรับการทำเช่นนั้นคือถ้าคุณต้องการลบเอนทิตีบางอย่างและไม่ใช่อื่น ๆ อย่างไรก็ตามคุณยังคงต้องตรวจสอบให้แน่ใจว่าคุณรักษาความสมบูรณ์ของการอ้างอิงไม่เช่นนั้นคุณจะไม่สามารถยืนยันการเปลี่ยนแปลงของคุณได้
เพียงแค่ลบที่จัดเก็บและสร้างใหม่ทั้งสองอย่างรวดเร็วและปลอดภัยและสามารถทำได้อย่างเป็นระบบที่รันไทม์
อัปเดตสำหรับ iOS5 +
ด้วยการแนะนำของที่เก็บข้อมูลไบนารีภายนอก (อนุญาตให้ภายนอก BinaryDataStorage หรือเก็บในไฟล์บันทึกภายนอก) ใน iOS 5 และ OS X 10.7 เพียงแค่การลบไฟล์ที่ชี้โดย storeURLs ไม่เพียงพอ คุณจะทิ้งไฟล์บันทึกภายนอกไว้ เนื่องจากรูปแบบการตั้งชื่อของไฟล์บันทึกภายนอกเหล่านี้ยังไม่เปิดเผยฉันยังไม่มีวิธีแก้ปัญหาสากล - an0 8 พฤษภาคม 2555 เวลา 23:00 น
คุณสามารถลบไฟล์ SQLite - แต่ฉันเลือกที่จะทำโดยล้างตารางแต่ละรายการด้วยฟังก์ชั่น:
- (void) deleteAllObjects: (NSString *) entityDescription {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityDescription inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *items = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
for (NSManagedObject *managedObject in items) {
[_managedObjectContext deleteObject:managedObject];
DLog(@"%@ object deleted",entityDescription);
}
if (![_managedObjectContext save:&error]) {
DLog(@"Error deleting %@ - error:%@",entityDescription,error);
}
}
เหตุผลที่ฉันเลือกที่จะทำทีละโต๊ะก็เพราะมันทำให้ฉันยืนยันในขณะที่ฉันกำลังเขียนโปรแกรมที่ลบเนื้อหาของตารางนั้นมีเหตุผลและไม่มีข้อมูลที่ฉันอยากจะเก็บไว้
การทำเช่นนี้จะช้ากว่าการลบไฟล์และฉันจะเปลี่ยนเป็นการลบไฟล์ถ้าฉันใช้วิธีนี้ใช้เวลานานเกินไป
ใช้NSBatchDeleteRequest
เพื่อลบวัตถุทั้งหมดในเอนทิตีโดยไม่ต้องโหลดลงในหน่วยความจำหรือวนซ้ำผ่านวัตถุเหล่านั้น
// create the delete request for the specified entity
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = MyEntity.fetchRequest()
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
// get reference to the persistent container
let persistentContainer = (UIApplication.shared.delegate as! AppDelegate).persistentContainer
// perform the delete
do {
try persistentContainer.viewContext.execute(deleteRequest)
} catch let error as NSError {
print(error)
}
รหัสนี้ได้รับการอัพเดตสำหรับ iOS 10 และ Swift 3 หากคุณต้องการรองรับ iOS 9 ให้ดูคำถามนี้
แหล่งที่มา:
moc.performBlockAndWait({ () -> Void in
})
ฉันได้เขียนclearStores
วิธีการที่ผ่านทุกร้านและลบทั้งจากผู้ประสานงานและระบบแฟ้ม (การจัดการข้อผิดพลาดซ้าย):
NSArray *stores = [persistentStoreCoordinator persistentStores];
for(NSPersistentStore *store in stores) {
[persistentStoreCoordinator removePersistentStore:store error:nil];
[[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
}
[persistentStoreCoordinator release], persistentStoreCoordinator = nil;
วิธีนี้อยู่ในcoreDataHelper
ชั้นเรียนที่ดูแล (เหนือสิ่งอื่นใด) เพื่อสร้าง persistentStore เมื่อมันเป็นศูนย์
ฉันลบข้อมูลทั้งหมดจากข้อมูลหลักในเหตุการณ์ปุ่มในคลาส HomeViewController: บทความนี้ช่วยฉันมากฉันคิดว่าฉันมีส่วนร่วม
-(IBAction)buttonReset:(id)sender
{
NSLog(@"buttonReset Pressed");
//Erase the persistent store from coordinator and also file manager.
NSPersistentStore *store = [self.persistentStoreCoordinator.persistentStores lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
[self.persistentStoreCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
NSLog(@"Data Reset");
//Make new persistent store for future saves (Taken From Above Answer)
if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}
}
โปรดทราบว่าเพื่อที่จะเรียกใช้ self.persistentStoreCoordinator ฉันประกาศคุณสมบัติใน Home View Controller (ไม่ต้องกังวลกับ managedObjectContext ที่ฉันใช้สำหรับการบันทึกและการโหลด)
@property (nonatomic, retain) NSManagedObjectContext * managedObjectContext;
@property (nonatomic, retain) NSPersistentStoreCoordinator * persistentStoreCoordinator;
จากนั้นใน AppDelegate ApplicationDidFinishLaunching ด้านล่างสร้าง HomeViewController ฉันมี:
homeViewController = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil];
homeViewController.managedObjectContext = self.managedObjectContext;
homeViewController.persistentStoreCoordinator = self.persistentStoreCoordinator;
MagicalRecordทำให้ง่ายมาก
[MyCoreDataObject MR_truncateAll];
MR_truncateAll
ไปยังพวกเขาอย่างไร?
iOS9 +, Swift 2
ลบวัตถุทั้งหมดในเอนทิตีทั้งหมด
func clearCoreDataStore() {
let entities = managedObjectModel.entities
for entity in entities {
let fetchRequest = NSFetchRequest(entityName: entity.name!)
let deleteReqest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try context.executeRequest(deleteReqest)
} catch {
print(error)
}
}
}
[ตอบช้าเมื่อตอบรับความโปรดปรานเพื่อขอคำตอบที่ใหม่กว่า]
ดูคำตอบก่อนหน้า
แต่มีวิธีที่แตกต่างและคล้ายกันในการลบที่เก็บถาวรที่ใช้งานได้ กุญแจสำคัญคือการวางไฟล์ที่เก็บถาวรของคุณในไดเรกทอรีย่อยของตัวเองที่ไม่มีสิ่งอื่นใด อย่าเพิ่งติดมันในไดเรกทอรีเอกสาร (หรือที่ใดก็ได้) สร้างไดเรกทอรีย่อยใหม่สำหรับเก็บถาวร เนื้อหาของไดเรกทอรีนั้นจะเป็นไฟล์เก็บถาวรไฟล์เจอร์นัลและไฟล์ไบนารีภายนอก หากคุณต้องการดักฟังที่เก็บข้อมูลทั้งหมดให้ลบไดเรกทอรีนั้นและพวกเขาทั้งหมดจะหายไป
คุณจะทำสิ่งนี้เมื่อตั้งค่าร้านค้าถาวรของคุณ:
NSURL *storeDirectoryURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"persistent-store"];
if ([[NSFileManager defaultManager] createDirectoryAtURL:storeDirectoryURL
withIntermediateDirectories:NO
attributes:nil
error:nil]) {
NSURL *storeURL = [storeDirectoryURL URLByAppendingPathComponent:@"MyApp.sqlite"];
// continue with storeURL as usual...
}
จากนั้นเมื่อคุณต้องการที่จะลบร้านค้า
[[NSFileManager defaultManager] removeItemAtURL:storeDirectoryURL error:nil];
ซึ่งจะลบทั้งไดเร็กทอรีย่อยที่กำหนดเองและไฟล์ Core Data ทั้งหมดในนั้นซ้ำ ๆ
นี้จะทำงานเฉพาะถ้าคุณไม่ได้มีการเก็บถาวรของคุณในโฟลเดอร์เดียวกันกับอื่น ๆ ข้อมูลที่สำคัญ เช่นเดียวกับไดเรกทอรีเอกสารซึ่งอาจมีสิ่งที่มีประโยชน์อื่น ๆ อยู่ในนั้น หากเป็นสถานการณ์ของคุณคุณจะได้รับผลเช่นเดียวกันโดยการมองหาไฟล์ที่คุณไม่ต้องการที่จะเก็บและลบทุกอย่างอื่น สิ่งที่ต้องการ:
NSString *docsDirectoryPath = [[self applicationDocumentsDirectory] path];
NSArray *docsDirectoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:docsDirectoryPath error:nil];
for (NSString *docsDirectoryItem in docsDirectoryContents) {
// Look at docsDirectoryItem. If it's something you want to keep, do nothing.
// If it's something you don't recognize, remove it.
}
วิธีนี้อาจเป็นข้อผิดพลาดง่าย คุณต้องแน่ใจว่าคุณรู้ทุกไฟล์ที่คุณต้องการเก็บไว้เพราะมิฉะนั้นคุณอาจลบข้อมูลสำคัญ ในทางกลับกันคุณสามารถลบไฟล์ไบนารีภายนอกโดยไม่ทราบชื่อไฟล์ / ไดเรกทอรีที่ใช้ในการจัดเก็บ
นี่คือการแก้ปัญหาแบบรวมสำหรับการล้างข้อมูล Core
- (void)deleteAllObjectsInCoreData
{
NSArray *allEntities = self.managedObjectModel.entities;
for (NSEntityDescription *entityDescription in allEntities)
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entityDescription];
fetchRequest.includesPropertyValues = NO;
fetchRequest.includesSubentities = NO;
NSError *error;
NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"Error requesting items from Core Data: %@", [error localizedDescription]);
}
for (NSManagedObject *managedObject in items) {
[self.managedObjectContext deleteObject:managedObject];
}
if (![self.managedObjectContext save:&error]) {
NSLog(@"Error deleting %@ - error:%@", entityDescription, [error localizedDescription]);
}
}
}
หากคุณต้องการลบวัตถุทั้งหมดและไม่ต้องการลบไฟล์สำรองคุณสามารถใช้วิธีการต่อไปนี้:
- (void)deleteAllObjectsInContext:(NSManagedObjectContext *)context
usingModel:(NSManagedObjectModel *)model
{
NSArray *entities = model.entities;
for (NSEntityDescription *entityDescription in entities) {
[self deleteAllObjectsWithEntityName:entityDescription.name
inContext:context];
}
}
- (void)deleteAllObjectsWithEntityName:(NSString *)entityName
inContext:(NSManagedObjectContext *)context
{
NSFetchRequest *fetchRequest =
[NSFetchRequest fetchRequestWithEntityName:entityName];
fetchRequest.includesPropertyValues = NO;
fetchRequest.includesSubentities = NO;
NSError *error;
NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *managedObject in items) {
[context deleteObject:managedObject];
NSLog(@"Deleted %@", entityName);
}
}
ระวังว่ามันอาจช้ามาก (ขึ้นอยู่กับจำนวนวัตถุในกราฟวัตถุของคุณ)
หากคุณต้องการลบเส้นทางของวัตถุทั้งหมด (ซึ่งง่ายกว่าการทำลาย Core Data stack แต่มีประสิทธิภาพน้อยกว่า) ซึ่งเป็นการใช้งานที่ดีกว่า:
- (void)deleteAllManagedObjectsInModel:(NSManagedObjectModel *)managedObjectModel context:(NSManagedObjectContext *)managedObjectContext
{
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
[managedObjectContext performBlockAndWait:^{
for (NSEntityDescription *entity in managedObjectModel) {
NSFetchRequest *fetchRequest = [NSFetchRequest new];
[fetchRequest setEntity:entity];
[fetchRequest setIncludesSubentities:NO];
NSArray *objects = [managedObjectContext executeFetchRequest:fetchRequest error:nil];
for (NSManagedObject *managedObject in objects) {
[managedObjectContext deleteObject:managedObject];
}
}
[managedObjectContext save:nil];
}];
}];
[operation setCompletionBlock:^{
// Do stuff once the truncation is complete
}];
[operation start];
}
การนำNSOperation
ไปใช้งานนี้ใช้เพื่อทำการลบเธรดหลักและแจ้งเตือนเมื่อเสร็จสิ้น คุณอาจต้องการส่งการแจ้งเตือนหรือบางสิ่งภายในบล็อกการทำให้เสร็จสมบูรณ์เพื่อทำให้ฟองสบู่สถานะกลับไปที่เธรดหลัก
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
เพื่อที่จะใช้วิธีนี้มิฉะนั้นคุณจะได้รับข้อผิดพลาด:Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.
โซลูชัน iOS 10 + Swift 3:
func clearCoreDataStore() {
let delegate = UIApplication.shared.delegate as! AppDelegate
let context = delegate.persistentContainer.viewContext
for i in 0...delegate.persistentContainer.managedObjectModel.entities.count-1 {
let entity = delegate.persistentContainer.managedObjectModel.entities[i]
do {
let query = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
let deleterequest = NSBatchDeleteRequest(fetchRequest: query)
try context.execute(deleterequest)
try context.save()
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
abort()
}
}
}
ทำซ้ำผ่านเอนทิตีข้อมูลหลักทั้งหมดและล้างข้อมูล
ขอบคุณสำหรับการโพสต์ ฉันติดตามมันและมันก็ได้ผลกับฉัน แต่ฉันมีปัญหาอื่นที่ไม่ได้กล่าวถึงในการตอบกลับใด ๆ ดังนั้นฉันไม่แน่ใจว่ามันเป็นเพียงฉัน
อย่างไรก็ตามคิดว่าฉันจะโพสต์ปัญหาที่นี่และวิธีการของฉันที่แก้ไขได้
ฉันมีบันทึกในฐานข้อมูลไม่กี่ฉันต้องการล้างทุกอย่างให้สะอาดก่อนเขียนข้อมูลใหม่ไปยังฐานข้อมูลดังนั้นฉันจึงทำทุกอย่างรวมถึง
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
แล้วใช้managedObjectContext
เพื่อเข้าถึงฐานข้อมูล (ควรว่างเปล่าในตอนนี้) ข้อมูลก็ยังอยู่ที่นั่น หลังจากที่ในขณะของการแก้ไขปัญหาที่ฉันพบว่าฉันต้องรีเซ็ตmanagedObjectContext
, managedObject
, managedObjectModel
และ
persistentStoreCoordinator
ก่อนที่ผมจะใช้managedObjectContext
ในการเข้าถึง dabase ตอนนี้ฉันมีฐานข้อมูลที่สะอาดที่จะเขียน
นี่เป็นเวอร์ชันที่ค่อนข้างง่ายโดยมีการเรียก AppDelegate ด้วยตนเองน้อยลงและรหัสสุดท้ายที่เหลือจากคำตอบยอดนิยม นอกจากนี้ฉันยังได้รับข้อผิดพลาด "ที่เก็บถาวรของวัตถุไม่สามารถเข้าถึงได้จากผู้ประสานงานของ NSManagedObjectContext นี้" ดังนั้นเพียงแค่ต้องการเพิ่มที่ด้านหลัง
NSPersistentStoreCoordinator *storeCoordinator = [self persistentStoreCoordinator];
NSPersistentStore *store = [[storeCoordinator persistentStores] lastObject];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"dataModel"];
NSError *error;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];
if (storeCoordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:storeCoordinator];
}
สวิฟท์โซลูชั่น:
class func deleteAllManagedObjects() {
let modelURL = NSBundle.mainBundle().URLForResource("some string", withExtension: "mom")
let mom = NSManagedObjectModel(contentsOfURL: modelURL)
for entityName in mom.entitiesByName.keys {
let fr = NSFetchRequest(entityName: entityName as String)
let a = Utility.managedObjectContext().executeFetchRequest(fr, error: nil) as [NSManagedObject]
for mo in a {
Utility.managedObjectContext().deleteObject(mo)
}
}
Utility.managedObjectContext().save(nil)
}
let modelURL = NSBundle.mainBundle().URLForResource("some string", withExtension: "momd")!
เป็นการอ้างอิงด่วนเพื่อบันทึกการค้นหาที่อื่น - สร้างที่จัดเก็บถาวรใหม่หลังจากลบแล้วสามารถทำได้ด้วย:
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}
คำตอบที่ดีสำหรับคำถามนี้ นี่คือข้อสรุปที่ดี สองบรรทัดแรกลบฐานข้อมูล sqlite จากนั้นวง for: จะลบวัตถุใด ๆ ในหน่วยความจำ managedObjectContext
NSURL *storeURL = [[(FXYAppDelegate*)[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory] URLByAppendingPathComponent:@"AppName.sqlite"];
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
for (NSManagedObject *ct in [self.managedObjectContext registeredObjects]) {
[self.managedObjectContext deleteObject:ct];
}
คุณยังสามารถค้นหาชื่อเอนทิตีทั้งหมดและลบออกโดยใช้ชื่อ มันเป็นรุ่นที่ยาวกว่า แต่ใช้งานได้ดีในแบบที่คุณไม่ต้องทำงานกับร้านขายติดตา
- (void)clearCoreData
{
NSError *error;
NSEntityDescription *des = [NSEntityDescription entityForName:@"Any_Entity_Name" inManagedObjectContext:_managedObjectContext];
NSManagedObjectModel *model = [des managedObjectModel];
NSArray *entityNames = [[model entities] valueForKey:@"name"];
for (NSString *entityName in entityNames){
NSFetchRequest *deleteAll = [NSFetchRequest fetchRequestWithEntityName:entityName];
NSArray *matches = [self.database.managedObjectContext executeFetchRequest:deleteAll error:&error];
}
if (matches.count > 0){
for (id obj in matches){
[_managedObjectContext deleteObject:obj];
}
[self.database.managedObjectContext save:&error];
}
}
สำหรับ "Any_Entity_Name" เพียงแค่ให้ชื่อใด ๆ ของเอนทิตี้ของคุณเราจะต้องหาคำอธิบายเอนทิตีที่เอนทิตีของคุณอยู่ภายใน ValueForKey @ "name" จะส่งคืนชื่อเอนทิตีทั้งหมด สุดท้ายอย่าลืมที่จะบันทึก
คำตอบที่ยอมรับนั้นถูกต้องโดยการลบ URL โดย NSFileManager นั้นถูกต้อง แต่ตามที่ระบุไว้ในการแก้ไข iOS 5+ ที่จัดเก็บแบบต่อเนื่องไม่ได้แสดงเพียงไฟล์เดียว สำหรับการจัดเก็บ SQLite เป็น * .sqlite, * .sqlite-shm และ * .sqlite-wal ... โชคดีตั้งแต่ iOS 7+ เราสามารถใช้วิธีการได้
ดูแลการลบดังนั้นรหัสควรเป็นดังนี้:
NSPersistentStore *store = ...;
NSError *error;
NSURL *storeURL = store.URL;
NSString *storeName = ...;
NSPersistentStoreCoordinator *storeCoordinator = ...;
[storeCoordinator removePersistentStore:store error:&error];
[NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:storeURL.path options:@{NSPersistentStoreUbiquitousContentNameKey: storeName} error:&error];
นี่คือเวอร์ชันที่ลบทุกระเบียนในทุกตารางที่คุณมี
สวิฟต์ 4
static func resetDatabase() {
do {
try dataStore.persistentStoreCoordinator.managedObjectModel.entities.forEach { (entity) in
if let name = entity.name {
let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: name)
let request = NSBatchDeleteRequest(fetchRequest: fetch)
try mainContext.execute(request)
}
}
try mainContext.save()
} catch {
print("error resenting the database: \(error.localizedDescription)")
}
}
Swift 4/5, iOS 9+
การสร้างCoreData
ไฟล์ SQLite ใหม่ทั้งหมดจะทำให้แน่ใจว่าข้อมูลทั้งหมดถูกลบดังนั้นเอนทิตีทั้งหมดจะถูกลบ แค่โทรdeleteAndRebuild()
มา
class CoreDataStack {
// Change this
static let datamodelName = "ProjectName"
static let storeType = "sqlite"
static let persistentContainer = NSPersistentContainer(name: datamodelName)
private static let url: URL = {
let url = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).\(storeType)")
assert(FileManager.default.fileExists(atPath: url.path))
return url
}()
static func loadStores() {
persistentContainer.loadPersistentStores(completionHandler: { (nsPersistentStoreDescription, error) in
if let error = error {
fatalError(error.localizedDescription)
}
})
}
static func deleteAndRebuild() {
try! persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: storeType, options: nil)
loadStores()
}
}
ใช้ได้กับทุกรุ่น ส่งชื่อเอนทิตีและวนซ้ำเพื่อลบรายการทั้งหมดและบันทึกบริบท
func deleteData(entityToFetch: String, completion: @escaping(_ returned: Bool) ->()) {
var context = NSManagedObjectContext()
if #available(iOS 10.0, *) {
context = self.persistentContainer.viewContext
} else {
context = self.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 10+ และ Swift (สมมติว่าคุณมีคลาส CoreDataManager):
let persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "<Data-Model-Name>“)
container.loadPersistentStores(completionHandler: { (storeDescription, err) in
if let err = err {
fatalError("loading of store failed: \(err)")
}
})
return container
}()
func resetPersistentStore() {
if let persistentStore = persistentContainer.persistentStoreCoordinator.persistentStores.last {
let storeURL = persistentContainer.persistentStoreCoordinator.url(for: persistentStore)
do {
try persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: storeURL, ofType: NSSQLiteStoreType, options: nil)
} catch {
print("failed to destroy persistent store:", error.localizedDescription)
}
do {
try persistentContainer.persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
} catch {
print("failed to re-add persistent store:", error.localizedDescription)
}
}
}
ข้อดีอย่างหนึ่งของวิธีนี้คือมันตรงไปตรงมามากขึ้นโดยเฉพาะเมื่อคุณมีการบันทึกข้อมูลจำนวนมากสำหรับเอนทิตีจำนวนมากในข้อมูลหลักของคุณ ในกรณีนี้คำขอลบแบตช์จะต้องใช้หน่วยความจำมาก
โซลูชัน Swift 5.1
public static func reset() {
let coordinator = _persistentContainer.persistentStoreCoordinator
for store in coordinator.persistentStores where store.url != nil {
try? coordinator.remove(store)
try? FileManager.default.removeItem(atPath: store.url!.path)
}
}
ลบไฟล์ร้านค้าถาวรและตั้งค่าผู้ประสานงานร้านค้าถาวรใหม่หรือไม่
สมมติว่าคุณกำลังใช้งานMagicalRecord
และมีที่เก็บข้อมูลเริ่มต้น:
ฉันไม่ชอบโซลูชันทั้งหมดที่สมมติว่ามีไฟล์บางไฟล์อยู่และ / หรือมีความต้องการป้อนชื่อเอนทิตี้หรือคลาส นี่เป็นวิธีที่รวดเร็วในการลบข้อมูลทั้งหมดออกจากเอนทิตีทั้งหมด หลังจากลบมันจะสร้างกองสดขึ้นมาใหม่ด้วย (จริง ๆ แล้วฉันไม่แน่ใจว่าจำเป็นต้องมีส่วนนี้อย่างไร)
เป็น godo สำหรับสถานการณ์สไตล์ "logout" เมื่อคุณต้องการลบทุกอย่าง แต่มีร้านค้าที่ใช้งานได้และกระทรวงพาณิชย์เพื่อรับข้อมูลใหม่ใน (เมื่อผู้ใช้ลงชื่อเข้าใช้ ... )
extension NSManagedObject {
class func dropAllData() {
MagicalRecord.saveWithBlock({ context in
for name in NSManagedObjectModel.MR_defaultManagedObjectModel().entitiesByName.keys {
do { try self.deleteAll(name, context: context) }
catch { print("⚠️ ✏️ Error when deleting \(name): \(error)") }
}
}) { done, err in
MagicalRecord.cleanUp()
MagicalRecord.setupCoreDataStackWithStoreNamed("myStoreName")
}
}
private class func deleteAll(name: String, context ctx: NSManagedObjectContext) throws {
let all = NSFetchRequest(entityName: name)
all.includesPropertyValues = false
let allObjs = try ctx.executeFetchRequest(all)
for obj in allObjs {
obj.MR_deleteEntityInContext(ctx)
}
}
}
ใช้สิ่งนี้
+(NSArray *)fetchDataFromEntity:(NSString *)entityName context:(NSManagedObjectContext *)context
{
NSFetchRequest * fetchRequest =[[NSFetchRequest alloc] init];
NSEntityDescription * CategoriesEntity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[fetchRequest setEntity:CategoriesEntity];
NSError * error;
NSInteger count = [context countForFetchRequest:fetchRequest error:&error];
if (count && count>0) {
NSArray * fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects && fetchedObjects.count>0) {
return fetchedObjects;
}else
return nil;
}
else
return nil;
}
+ (void)deleteObjectsOfArray:(NSMutableArray*)ary context:(NSManagedObjectContext *)context {
for (NSManagedObject * obj in ary) {
[context deleteObject:obj];
}
NSError *saveError = nil;
[context save:&saveError];
}
+ (void)deleteEntity:(NSString *)entityName context:(NSManagedObjectContext *)context {
NSArray *listArray = [self fetchDataFromEntity:entityName context:context];
[self deleteObjectsOfArray:[NSMutableArray arrayWithArray:listArray] context:context];
}
ฉันใช้รหัสของ Grouchal และเพิ่มความเร็วฉันใช้การแจงนับพร้อมโหมดการทำงานพร้อมกัน ( NSEnumerationConcurrent
) มันเร็วขึ้นเล็กน้อยเมื่อเทียบกับการวนซ้ำ (ในแอปของฉันฉันเพิ่มคุณสมบัตินี้สำหรับผู้ทดสอบเพื่อล้างข้อมูลและทำการทดสอบแทนการลบและ ติดตั้งแอพ)
- (void)resetObjects
{
[self deleteAllObjectsInEntity:@"Entity1"];
[self deleteAllObjectsInEntity:@"Entity2"];
[self deleteAllObjectsInEntity:@"Entity3"];
[self deleteAllObjectsInEntity:@"Entity4"];
}
-(void) deleteAllObjectsInEntity:(NSString*) entityName
{
MainDataContext *coreDataContext = [MainDataContext sharedInstance];
NSManagedObjectContext *currentContext = coreDataContext.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:currentContext];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *items = [currentContext executeFetchRequest:fetchRequest error:&error];
[items enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSManagedObject * obj, NSUInteger idx, BOOL *stop) {
[currentContext deleteObject:obj];
}];
if (![currentContext save:&error]) {
NSLog(@"Error deleting %@ - error:%@",entityName,error);
}
}
ที่นี่รุ่น swift3 ของฉันสำหรับลบบันทึกทั้งหมด 'ผู้ใช้' เป็นชื่อเอนทิตี
@IBAction func btnDelAll_touchupinside(_ sender: Any) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchReq = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
let req = NSBatchDeleteRequest(fetchRequest: fetchReq)
do {
try managedObjectContext.execute(req)
} catch {
// Error Handling
}
}
NSBatchDeleteRequest
ใช้ stackoverflow.com/a/31961330/3681880