您知道有什么方法可以删除存储在Core Data中的所有条目吗?我的schema应该保持不变;我只想把它重置为空白。
Edit
我希望以编程方式做到这一点,这样用户就可以基本上按下重置按钮。
您知道有什么方法可以删除存储在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);
}
}
我选择逐表执行的原因是,它使我在编程时确认删除表的内容是合理的,并且没有我宁愿保留的数据。
这样做会比仅仅删除文件慢得多,如果我这个方法花费太长时间,我将更改为文件删除。
其他回答
我写了一个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。
迅速的解决方案:
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)
}
如果你想删除所有对象(这比拆除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来执行主线程的删除,并在完成时通知。您可能希望在完成块中发出通知或其他内容,以便将状态冒泡回主线程。
我经常使用的另一种方法(除了删除批处理请求)(基于应用程序需求)是重置持久存储。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)
}
}