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


Edit

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


当前回答

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

}

这种方法的一个优点是,它更直接,特别是当您在核心数据中有大量实体的数据记录时。在这种情况下,删除批处理请求将占用大量内存。

其他回答

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

MagicalRecord使这非常简单。

[MyCoreDataObject MR_truncateAll];

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

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

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

迅速的解决方案:

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