删除/重置核心数据中的所有条目?

你知道有什么办法删除存储在Core Data中的所有条目吗? 我的模式应该保持不变; 我只是想重置它为空白。


编辑

我正在寻找这样做以编程方式,使用户可以基本上打一个resetbutton。

您仍然可以使用NSFileManager:removeItemAtPath ::方法以编程方式删除文件。

 NSPersistentStore *store = ...; NSError *error; NSURL *storeURL = store.URL; NSPersistentStoreCoordinator *storeCoordinator = ...; [storeCoordinator removePersistentStore:store error:&error]; [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error]; 

然后,只需添加持久性存储以确保正确地重新创build。

遍历每个实体的编程方式比较慢,容易出错。 这样做的用法是如果你想删除一些实体而不是其他的。 但是,您仍然需要确保保持参照完整性,否则您将无法保留更改。

只需删除存储并重新创build它既快速又安全,并且可以在运行时以编程方式完成。

更新iOS5 +

通过在iOS 5和OS X 10.7中引入外部二进制存储(允许外部二进制数据存储或存储在外部logging文件中),仅删除storeURL指向的文件是不够的。 您将留下外部logging文件。 由于这些外部logging文件的命名方式不公开,所以我还没有一个通用的解决scheme。 – an0 5月8日在23:00

您可以删除sqllite文件 – 但我select通过使用函数单独清除表来执行此操作:

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

我之所以select这样做,是因为我在做编程时确认删除表格的内容是明智的,并且没有我宁愿保留的数据。

这样做会比只是删除文件慢得多,我会改变到一个文件删除,如果我这个方法需要太长时间。

适用于iOS 9+的更新解决scheme

使用NSBatchDeleteRequest删除实体中的所有对象,而不必将它们加载到内存中或遍历它们。

 // create the delete request for the specified entity let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "MyEntity") 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,请参阅此问题 。

资料来源:

  • 核心数据:删除一个实体的所有实例的最快方法 (包括Objective-C代码)
  • 核心数据新增function (WWDC 2015video)
  • 核心数据新特性 (WWDC 2016video)
  • 如何在iOS 10中使用核心数据
  • Core Data Swift 3.0中的新function

我写了一个clearStores方法,它遍历每个存储并从协调器和文件系统中删除它(留下的error handling):

 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类中的,它负责(除其他之外)在coreDataHelper创buildpersistentStore。

我从一个button上的核心数据中删除所有的数据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下创build一个HomeViewController,我有:

 homeViewController = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil]; homeViewController.managedObjectContext = self.managedObjectContext; homeViewController.persistentStoreCoordinator = self.persistentStoreCoordinator; 

MagicalRecord使这非常简单。

 [MyCoreDataObject MR_truncateAll]; 

[回复最新回复]

回顾早些时候的答案,

  • 根据@Grouchal和其他人的build议,提取和删除所有项目仍然是一个有效且有用的解决scheme。 如果你有非常大的数据存储,那么它可能会很慢,但它仍然工作得很好。
  • 就像你和@groundhog所说的那样,简单地删除数据存储就不再有效了。 即使您不使用外部二进制存储,它也是过时的,因为iOS 7使用WAL模式进行SQLite日记。 使用WAL模式,可能会有(可能较大的)日志文件围绕任何Core Data持久性存储。

但是有一个不同的,类似的方法来删除持久存储的工作。 关键是把你的持久性存储文件放在它自己的不包含其他东西的子目录中。 不要只将其粘贴在文档目录(或任何地方)中,只需要为持久性存储创build一个新的子目录即可。 该目录的内容最终将成为持久存储文件,日志文件和外部二进制文件。 如果你想核整个数据存储,删除那个目录,它们将全部消失。

设置持久性存储时,您可以这样做:

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

这recursion地删除自定义子目录和其中的所有核心数据文件。

这只有在您的持久存储与其他重要数据不在同一文件夹中时才有效 。 像文件目录,其中可能有其他有用的东西。 如果这是你的情况,你可以通过查找你想保留的文件并删除其他所有文件来获得相同的效果。 就像是:

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

这种方法可能容易出错 。 你必须确保你知道你想保留的每一个文件,否则你可能会删除重要的数据。 另一方面,您可以删除外部二进制文件,而不必知道用于存储它们的文件/目录名称。

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

如果要删除所有对象并且不想删除备份文件,可以使用以下方法:

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

请注意,这可能非常慢(取决于对象图中有多less个对象)。

这里是清除核心数据的联合解决scheme。

 - (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)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从主线程执行删除,并在完成时通知。 您可能想要在完成块中发出通知或其他内容,将状态回滚到主线程。

这是一个稍微简化的版本,对AppDelegate self的调用次数较less,最后一个代码没有被评分最高的答案。 此外,我得到一个错误“对象的持久性存储无法从此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]; } 

迅捷的解决scheme:

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

作为保存search的快速参考 – 在删除之后重新创build持久性存储可以通过以下方式完成:

 if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { // do something with the error } 

感谢您的post。 我跟着它,它为我工作。 但是我还有另外一个问题在答复中没有提到。 所以我不确定是不是只有我。

无论如何,我以为我会在这里发布的问题和我的方式,解决它。

我在数据库中有几条logging,在将新数据写入数据库之前,我想清除一切,因此我做了所有的事情

 [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error]; 

然后使用managedObjectContext来访问数据库(现在应该是空的),不知何故数据仍然存在。 经过一段时间的故障排除后,我发现我需要重置managedObjectContextmanagedObjectmanagedObjectModelpersistentStoreCoordinator ,然后才使用managedObjectContext访问dabase。 现在我有一个干净的数据库写入。

这个问题的几个很好的答案。 这是一个很好的简洁的。 前两行删除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]; } 

iOS 10 + Swift 3解决scheme:

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

遍历所有核心数据实体并清除它们

你也可以find所有的实体名称,并删除它们的名字。 它是一个更长的版本,但效果很好,这样你就不必使用持久性存储

  - (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”将返回所有的实体名称。 最后,不要忘记保存。

被接受的答案是正确的,通过删除NSFileManager的URL是正确的,但正如iOS 5 +编辑所述,持久性存储不只是由一个文件表示。 对于SQLite存储是* .sqlite,* .sqlite-shm和* .sqlite-wal …幸运的是,从iOS 7+我们可以使用方法

[NSPersistentStoreCoordinator + removeUbiquitousContentAndPersistentStoreAtURL:options:error:]

照顾清除,所以代码应该是这样的:

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

iOS 10和Swift 3

假设你的实体名称是“Photo”,并且你创build了一个CoreDataStack类…

  func clearData() { do { let context = CoreDataStack.sharedInstance.persistentContainer.viewContext let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Photo") do { let objects = try context.fetch(fetchRequest) as? [NSManagedObject] _ = objects.map{$0.map{context.delete($0)}} CoreDataStack.sharedInstance.saveContext() } catch let error { print("ERROR DELETING : \(error)") } } } 

这里是一个很好的教程,介绍如何使用CoreData以及如何使用这个方法。 https://medium.com/compileswift/parsing-json-response-and-save-it-in-coredata-step-by-step-fb58fc6ce16f#.1tu6kt8qb

从你的fileURLPath中删除sqlite,然后build立。

假设你正在使用MagicalRecord并有一个默认的持久性存储:

我不喜欢假定某些文件存在的所有解决scheme和/或要求input实体名称或类。 这是一个Swift(2),从所有实体中删除所有数据的安全方法。 删除后,它也会重新创build一个新的堆栈(我实际上不确定这个部分是多么的严重)。

当你想删除一切,但有一个工作的商店和moc获取新的数据(一旦用户login…)“注销”风格的情况下,

 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 ),它比循环快了一点(在我的应用程序,我为testing人员添加了这个function,以便他们可以清除数据和做testing用例,而不是删除并安装应用程序)

 - (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版本删除所有logging。 “用户”是实体名称

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

适用于所有版本。 通过实体名称并迭代以删除所有条目并保存上下文。

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

删除持久存储文件并设置新的持久存储协调器?

你们都让这看起来很复杂。 您可以发送您的NSManagedObjectContext重置方法