您知道有什么方法可以删除存储在Core Data中的所有条目吗?我的schema应该保持不变;我只想把它重置为空白。
Edit
我希望以编程方式做到这一点,这样用户就可以基本上按下重置按钮。
您知道有什么方法可以删除存储在Core Data中的所有条目吗?我的schema应该保持不变;我只想把它重置为空白。
Edit
我希望以编程方式做到这一点,这样用户就可以基本上按下重置按钮。
当前回答
您仍然可以使用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
其他回答
我经常使用的另一种方法(除了删除批处理请求)(基于应用程序需求)是重置持久存储。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)
}
}
}
这种方法的一个优点是,它更直接,特别是当您在核心数据中有大量实体的数据记录时。在这种情况下,删除批处理请求将占用大量内存。
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
这个问题有几个很好的答案。这里有一个简洁的例子。前两行删除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];
}
使用这个
+(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];
}
似乎有两种方法:
假设您的核心数据堆栈有一个典型的单例。
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()”是在初始化之后。)
方法一在开发过程中可能更有用。方法二在生产中可能更有用(在相对不常见的情况下,由于某种原因需要擦除所有内容)。