我对CoreData和使用它的这个应用程序很新。 我正在开发一种功能,可以在我在应用程序中注销时清除整个核心数据。
我有2个sqllite文件(出于某种原因,他们认为这很方便)
如何清除所有数据的两个文件并将其重置为无数据状态?
我已经尝试了很多方法,按照指南,在SO。
How to clear/reset all CoreData in one-to-many relationship
how to remove all objects from Core Data
他们似乎都对我失败了。 现在我想知道我做错了什么?也许有人可以解释我如何以正确的方式重置我的2个CoreData文件。
编辑:
//should clear the whole coredata database. mainly used for logout mechanism
-(void)resetCoreData
{
for (NSPersistentStore *store in self.persistentStoreCoordinator.persistentStores)
{
// NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0];
NSError *error;
NSURL *storeURL = store.URL;
DLog(@"storeURL: %@", storeURL);
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
DLog(@"There are erreurs: %@", error);
// [self addDefaultData];
}
_persistentStoreCoordinator = nil;
_managedObjectContext = nil;
_managedObjectModel = nil;
}
这似乎并没有为我清除CoreData。
EDIT2:
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyName" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSString *storePath = [[self applicationDocumentsDirectory]
stringByAppendingPathComponent:@"MyName.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"MyName" ofType:@"momd"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
}
}
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
//Check to see what version of the current model we're in. If it's >= 2.0,
//then and ONLY then check if migration has been performed...
NSSet *versionIdentifiers = [[self managedObjectModel] versionIdentifiers];
DLog(@"Which Current Version is our .xcdatamodeld file set to? %@", versionIdentifiers);
if ([versionIdentifiers containsObject:@"2.0"])
{
BOOL hasMigrated = YES;
if (hasMigrated==YES) {
storePath = nil;
storePath = [[self applicationDocumentsDirectory]
stringByAppendingPathComponent:@"MyName2.sqlite"];
}
}
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSError *error;
NSDictionary *pscOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption,
nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeUrl
options:pscOptions
error:&error]) {
DLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
编辑3: 我仍然在寻找一种方法来重置我的CoreData,就好像我删除了整个应用程序并重新启动它一样。这样做的通常方法对我的情况不起作用。并且有2个sqllite文件。在应用程序的某个时刻发生了迁移的提示,但我不太确定何时以及如何进行迁移。错误日志显示没什么用处。
我不是在寻找最有效的方法。就这样。
编辑4: 最后结果: 似乎我的遗留代码实例化了第二个ManagedObjectContext。我检索它的那一刻,并用它做了冲洗功能。两个sqlite文件都根据需要消失了。
感谢所有努力解决我的问题。
答案 0 :(得分:38)
尝试以下方法来刷新数据库,它对我来说非常适合。
-(void) flushDatabase{
[__managedObjectContext lock];
NSArray *stores = [__persistentStoreCoordinator persistentStores];
for(NSPersistentStore *store in stores) {
[__persistentStoreCoordinator removePersistentStore:store error:nil];
[[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
}
[__managedObjectContext unlock];
__managedObjectModel = nil;
__managedObjectContext = nil;
__persistentStoreCoordinator = nil;
}
答案 1 :(得分:2)
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
因此,您要从持久性存储协调器中删除持久性存储,然后尝试删除该文件。但是只是从协调器中删除存储不足以保证与存储关联的文件已关闭,如果没有,则文件系统可能会阻止您删除该文件。我无法从你的问题中看出你是否在这里使用ARC,但是因为你说这是旧的代码,你很可能不是。无论哪种方式,如果删除商店导致它被自动释放而不是释放,或者如果你在任何地方保留对商店的任何其他引用,那么仅仅因为你从协调器中删除它而不会释放存储,文件可能保持打开状态,删除文件将失败。
除了查看-removeItemAtPath:error:
提供的错误对象之外,查看实际情况的一个好方法是查看文件系统,看看在尝试之后文件是否仍然存在去掉它。转到“管理器”窗口,选择您的设备和应用程序,然后下载应用程序沙箱的副本。然后,您应该能够看到文件是否真的被删除。
如果您确实看到文件正在被删除,那么请查找可以恢复数据的其他方法。如果UserA注销然后UserB在应用程序仍在运行时登录到该应用程序,您确定已经开始使用新的托管对象上下文吗? UserA的数据是否可能保留在MOC中?然后可以在创建和添加新商店时将其写出。我遇到的另一种可能性是iCloud在这里“帮助”。我看到您的数据文件保存在Documents目录中,iOS通常会尝试将该目录中的文件备份到iCloud。也许当您为UserB的数据创建新商店时,iCloud会将UserA的记录添加回该商店。 (似乎不太可能 - 我非常确定iCloud比那更复杂 - 但需要检查一下。)
答案 2 :(得分:1)
我在我的一个应用程序的AppDelegate中使用此功能......
- (void)deleteAllCoreData
{
NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0];
NSError *error;
NSURL *storeURL = store.URL;
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
__persistentStoreCoordinator = nil;
__managedObjectContext = nil;
__managedObjectModel = nil;
[self addDefaultData];
}
删除CoreData使用的持久存储,并将其保留,以便在再次访问核心数据时设置新的存储。
这是您提供的第二个链接中描述的方法。
答案 3 :(得分:1)
如果您的应用可以创建文件,那么只需在应用退出时删除它们。 如果您对数据库的某些概念具有有价值的架构信息,并且您只需要截断该文件,那么核心数据就不是这种情况......架构在已编译的实体模型和xcwhatever文件中。
另外我一定是读错了,因为如果你想要核心数据不是持久的那么你使用的是错误的工具。