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


Edit

我希望以编程方式做到这一点,这样用户就可以基本上按下重置按钮。


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


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

}

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

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


从fileURLPath中删除sqlite,然后构建。


您仍然可以使用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+更新

随着iOS 5和OS X 10.7引入外部二进制存储(allowsExternalBinaryDataStorage或Store in external Record File),简单地删除由storeurl指向的文件是不够的。你会留下外部记录文件。由于这些外部记录文件的命名方案不是公开的,所以我还没有一个通用的解决方案。- 12年5月8日23:00


我写了一个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为nil时创建persistentStore。


MagicalRecord使这非常简单。

[MyCoreDataObject MR_truncateAll];

作为一个快速参考,以节省在其他地方搜索-删除后重新创建持久存储可以用:

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

我从一个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。我在主视图控制器中声明了一个属性。(不要担心我用来保存和加载的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;

谢谢你的帖子。我遵循了它,它对我很有效。但我有另一个问题,在任何回复中都没有提到。所以我不确定是不是只有我一个人。

不管怎样,我想我应该把这个问题和我解决它的方法贴在这里。

我在数据库中有一些记录,我想在写新数据到db之前清除所有的东西,所以我做了包括

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

然后使用managedObjectContext访问数据库(现在应该是空的),数据仍然存在。 经过一段时间的故障排除后,我发现需要重置managedObjectContext、managedObject、managedObjectModel和 persistentStoreCoordinator,然后使用managedObjectContext访问数据库。现在我有了一个可以写入的干净数据库。


你们都把事情搞复杂了。你可以发送你的NSManagedObjectContext重置方法


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

下面是一个稍微简化的版本,减少了对AppDelegate self的调用,并且去掉了排名最高的答案中的最后一点代码。此外,我得到了一个错误“对象的持久存储无法从这个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];
}

您还可以查找所有实体名称,并按名称删除它们。它是一个较长的版本,但工作得很好,这样你就不必使用持久性存储

 - (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"将返回所有实体名称。最后,别忘了保存。


如果你想删除所有对象(这比拆除Core Data堆栈简单得多,但性能较差),那么这是一个更好的实现:

- (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来执行主线程的删除,并在完成时通知。您可能希望在完成块中发出通知或其他内容,以便将状态冒泡回主线程。


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

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

注意它可能非常慢(取决于对象图中有多少对象)。


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

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

[对请求更新回复的赏金的响应延迟]

回顾之前的答案,

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 storage because 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.

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.

在设置持久化存储时,你会这样做:

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文件。

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

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

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


迅速的解决方案:

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

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

[NSPersistentStoreCoordinator + removeUbiquitousContentAndPersistentStoreAtURL选项:错误:):

为了处理删除,代码应该是这样的:

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+的更新解决方案

使用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 {
    print(error.localizedDescription)
}

此代码已更新为iOS 10和Swift 3。如果你需要支持iOS 9,请看这个问题。

来源:

核心数据:删除实体的所有实例的最快方法(包括Objective-C代码) Core Data的新内容(WWDC 2015视频) Core Data的新内容(WWDC 2016视频) 如何在iOS 10中使用核心数据 Core Data Swift 3.0有什么新功能


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

我不喜欢所有假设存在特定文件和/或要求输入实体名称或类的解决方案。这是一个Swift(2),安全的方式删除所有实体的所有数据。删除后,它将重新创建一个新的堆栈(我实际上不确定这部分是多么必要)。

这是godo的“注销”风格的情况下,当你想删除一切,但有一个工作的存储和moc,以获得新的数据(一旦用户登录…)

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

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

龙道9+ 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)
        }
    }
}

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

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


这里我的swift3版本删除所有记录。'Users'是实体名称

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

iOS 10和Swift 3

假设您的实体名称是“Photo”,并且您创建了一个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


下面这个版本可以删除每个表中的每条记录。

斯威夫特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)")
    }
}

我经常使用的另一种方法(除了删除批处理请求)(基于应用程序需求)是重置持久存储。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)
    }
}

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

似乎有两种方法:

假设您的核心数据堆栈有一个典型的单例。

import CoreData
public let core = Core.shared
public final class Core {
    static let shared = Core()
    var container: NSPersistentContainer!
    private init() {
        container = NSPersistentContainer(name: "stuff")
        //deleteSql()
        container.loadPersistentStores { storeDescription, error in
            if let error = error { print("Error loading... \(error)") }
        }
        //deleteAll()
    }
    
    func saveContext() { // typical save helper
        if container.viewContext.hasChanges {
            do { try container.viewContext.save()
            } catch { print("Error saving... \(error)") }
        }
    }
    

然后……

    func deleteSql() {
        let url = FileManager.default.urls(
           for: .applicationSupportDirectory,
           in: .userDomainMask)[0].appendingPathComponent( "stuff.sqlite" )
        
        guard FileManager.default.fileExists(atPath: url.path) else {
            print("nothing to delete!")
            return
        }
        
        do {
            try container.persistentStoreCoordinator.destroyPersistentStore(
                at: url, ofType: "sqlite", options: nil)
            print("totally scorched the sql file. you DO now have to LOAD again")
        }
        catch {
            print("there was no sql file there!")
        }
    }
    
    func deleteAll() { // courtesy @Politta
        for e in container.persistentStoreCoordinator.managedObjectModel.entities {
            let r = NSBatchDeleteRequest(
              fetchRequest: NSFetchRequest(entityName: e.name ?? ""))
            let _ = try? container.viewContext.execute(r)
        }
        saveContext()
        print("conventionally deleted everything from within core data. carry on")
    }
}

.

1. 焦化SQL文件

感谢优秀的@J。能源部的答案。您完全销毁了sql文件。

你必须这样做

在加载核心数据之前,即在创建容器之后,但是 在真正载入商店之前。)

(注意示例代码“//deleteSql()”就在初始化之前。)

2. 逐个删除核心数据中的所有内容

感谢精彩的@Politta回答。一旦core data启动并运行,就可以随时执行此操作。

(注意示例代码“//deleteAll()”是在初始化之后。)

方法一在开发过程中可能更有用。方法二在生产中可能更有用(在相对不常见的情况下,由于某种原因需要擦除所有内容)。