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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1077810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:06:35  来源:igfitidea点击:

Delete/Reset all entries in Core Data?

ioscocoacocoa-touchcore-datansmanagedobject

提问by Michael Grinich

Do you know of any way to delete all of the entries stored in Core Data? My schema should stay the same; I just want to reset it to blank.

你知道有什么方法可以删除存储在 Core Data 中的所有条目吗?我的架构应该保持不变;我只想将其重置为空白。



Edit

编辑

I'm looking to do this programmatically so that a user can essentially hit a resetbutton.

我希望以编程方式执行此操作,以便用户基本上可以点击reset按钮。

采纳答案by groundhog

You can still delete the file programmatically, using the NSFileManager:removeItemAtPath:: method.

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

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

Then, just add the persistent store back to ensure it is recreated properly.

然后,只需添加回持久存储以确保正确重新创建它。

The programmatic way for iterating through each entity is both slower and prone to error. The use for doing it that way is if you want to delete some entities and not others. However you still need to make sure you retain referential integrity or you won't be able to persist your changes.

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

Just removing the store and recreating it is both fast and safe, and can certainly be done programatically at runtime.

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

Update for iOS5+

iOS5+ 更新

With the introduction of external binary storage (allowsExternalBinaryDataStorage or Store in External Record File) in iOS 5 and OS X 10.7, simply deleting files pointed by storeURLs is not enough. You'll leave the external record files behind. Since the naming scheme of these external record files is not public, I don't have a universal solution yet. – an0 May 8 '12 at 23:00

随着 iOS 5 和 OS X 10.7 中引入外部二进制存储(allowsExternalBinaryDataStorage 或 Store in External Record File),仅仅删除 storeURLs 指向的文件是不够的。您将留下外部记录文件。由于这些外部记录文件的命名方案是不公开的,所以我还没有一个通用的解决方案。– an0 2012 年 5 月 8 日 23:00

回答by Grouchal

You can delete the SQLite file - but I choose to do it by purging the tables individually with a functions:

您可以删除 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);
    }

}

The reason I chose to do it table by table is that it makes me confirm as I am doing the programming that deleting the contents of the table is sensible and there is not data that I would rather keep.

我选择逐表执行的原因是它让我在进行编程时确认删除表的内容是明智的,并且没有我宁愿保留的数据。

Doing it this will is much slower than just deleting the file and I will change to a file delete if I this method takes too long.

这样做比仅仅删除文件要慢得多,如果我这个方法花费的时间太长,我将更改为文件删除。

回答by Suragch

Updated Solution for iOS 10+

适用于 iOS 10+ 的更新解决方案

Use NSBatchDeleteRequestto delete all objects in the entity without having to load them into memory or iterate through them.

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

This code has been updated for iOS 10 and Swift 3. If you need to support iOS 9, see this question.

此代码已针对 iOS 10 和 Swift 3 进行了更新。如果您需要支持 iOS 9,请参阅此问题

Sources:

资料来源:

回答by samvermette

I've written a clearStoresmethod that goes through every store and delete it both from the coordinator and the filesystem (error handling left aside):

我编写了一个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;

This method is inside a coreDataHelperclass that takes care of (among other things) creating the persistentStore when it's nil.

此方法位于一个coreDataHelper类中,该类负责(除其他事项外)在它为零时创建 persistentStore。

回答by atreat

I remove all data from core data on a button Event in a HomeViewController class: This article helped me so much I figured I'd contribute.

我从 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
    }

}

Note that in order to call self.persistentStoreCoordinator I declared a property in the Home View Controller. (Don't worry about the managedObjectContext that I use for saving and loading.)

请注意,为了调用 self.persistentStoreCoordinator,我在主视图控制器中声明了一个属性。(不用担心我用于保存和加载的 managedObjectContext。)

@property (nonatomic, retain) NSManagedObjectContext        *   managedObjectContext;
@property (nonatomic, retain) NSPersistentStoreCoordinator  *   persistentStoreCoordinator;

Then in the AppDelegate ApplicationDidFinishLaunching right below creating a HomeViewController I have :

然后在 AppDelegate ApplicationDidFinishLaunching 下面创建一个 HomeViewController 我有:

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

回答by Brian King

MagicalRecordmakes this very easy.

MagicalRecord使这变得非常容易。

[MyCoreDataObject MR_truncateAll];

回答by Andres Wang

iOS9+, Swift 2

iOS9+,Swift 2

Delete all objects in all entities

删除所有实体中的所有对象

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

回答by Tom Harrington

[Late answer in response to a bounty asking for newer responses]

[回应悬赏要求更新回复的迟到答复]

Looking over earlier answers,

看了之前的回答,

  • Fetching and deleting all items, as suggested by @Grouchal and others, is still an effective and useful solution. If you have very large data stores then it might be slow, but it still works very well.
  • Simply removing the data store is, as you and @groundhog note, no longer effective. It's obsolete even if you don't use external binary storagebecause iOS 7 uses WAL mode for SQLite journalling. With WAL mode there may be (potentially large) journal files sitting around for any Core Data persistent store.
  • 正如@Grouchal 和其他人所建议的那样,获取和删除所有项目仍然是一种有效且有用的解决方案。如果您有非常大的数据存储,那么它可能会很慢,但它仍然可以很好地工作。
  • 正如您和@groundhog 所指出的那样,简单地删除数据存储不再有效。即使您不使用外部二进制存储,它也已过时,因为 iOS 7 使用 WAL 模式进行 SQLite 日志记录。在 WAL 模式下,可能会有(可能很大)日志文件用于任何 Core Data 持久存储。

But there's a different, similar approach to removing the persistent store that does work. The key is to put your persistent store file in its own sub-directory that doesn't contain anything else. Don't just stick it in the documents directory (or wherever), create a new sub-directory just for the persistent store. The contents of that directory will end up being the persistent store file, the journal files, and the external binary files. If you want to nuke the entire data store, delete that directory and they'll all disappear.

但是有一种不同的、类似的方法可以删除有效的持久存储。关键是将您的持久存储文件放在它自己的不包含任何其他内容的子目录中。不要只是把它放在文档目录(或任何地方)中,为持久存储创建一个新的子目录。该目录的内容最终将成为持久存储文件、日志文件和外部二进制文件。如果您想破坏整个数据存储,请删除该目录,它们将全部消失。

You'd do something like this when setting up your persistent store:

在设置持久存储时,您会执行以下操作:

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

Then when you wanted to remove the store,

然后当你想删除商店时,

[[NSFileManager defaultManager] removeItemAtURL:storeDirectoryURL error:nil];

That recursively removes both the custom sub-directory and all of the Core Data files in it.

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

This only works if you don't already have your persistent store in the same folder as other, important data. Like the documents directory, which probably has other useful stuff in it. If that's your situation, you could get the same effect by looking for files that you dowant to keep and removing everything else. Something like:

这仅适用于您尚未将持久存储与其他重要数据位于同一文件夹中的情况。就像文档目录一样,其中可能还有其他有用的东西。如果这是你的情况,你可以通过查找文件,您得到相同的效果希望保持和消除其他一切。就像是:

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

This approach may be error prone. You've got to be absolutely sure that you know everyfile you want to keep, because otherwise you might remove important data. On the other hand, you can remove the external binary files without actually knowing the file/directory name used to store them.

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

回答by GxocT

Here is combined solution for purging Core Data.

这是清除核心数据的组合解决方案。

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

回答by Marián ?erny

If you want to delete all objects and do not want to delete the backing files, you can use following methods:

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

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

Beware that it may be very slow (depends on how many objects are in your object graph).

请注意,它可能会非常慢(取决于对象图中的对象数量)。