删除以前的 sqlite 存储文件后重新创建持久性存储
Posted
技术标签:
【中文标题】删除以前的 sqlite 存储文件后重新创建持久性存储【英文标题】:Recreate persistence store after removing previous sqlite store file 【发布时间】:2011-09-16 07:34:43 【问题描述】:我想删除我的 sql lite 文件并再次设置持久性存储。
//Explicitly write Core Data accessors
- (NSManagedObjectContext *) managedObjectContext
if (managedObjectContext != nil)
return managedObjectContext;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
return managedObjectContext;
- (void) setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
- (NSManagedObjectModel *)managedObjectModel
if (managedObjectModel != nil)
return managedObjectModel;
managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil] ;
return managedObjectModel;
-(void) setManagedObjectModel:(NSManagedObjectModel *)managedObjectModel
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
if (persistentStoreCoordinator != nil)
return persistentStoreCoordinator;
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Port.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error])
NSLog(@"Could not create store .... %@", error );
/*Error for store creation should be handled in here*/
return persistentStoreCoordinator;
我正在尝试像这样重置我的场景
- (void)reset
// Release CoreData chain
self.managedObjectContext = nil;
self.managedObjectModel = nil;
self.persistentStoreCoordinator = nil;
// Delete the sqlite file
NSError *error = nil;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Port.sqlite"]];
if ([fileManager fileExistsAtPath:storeUrl.path])
[fileManager removeItemAtURL:storeUrl error:&error];
self.managedObjectContext = [self managedObjectContext];
self.managedObjectModel = [self managedObjectModel];
self.persistentStoreCoordinator = [self persistentStoreCoordinator];
// handle error...
保存时出现错误:
+ (BOOL)saveAll
// [self createStorage];
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = [(WSSMobileAppsAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
if (![managedObjectContext save:&error])
NSLog(@"Error while saving %@", error);
return FALSE;
return TRUE;
错误:
Error while saving Error Domain=NSCocoaErrorDomain Code=134030 "The operation couldn’t be completed. (Cocoa error 134030.)" UserInfo=0x7195ac0 NSAffectedStoresErrorKey=(
"<NSSQLCore: 0x714eee0> (URL: file://localhost/Users/.../Library/Application%20Support/iPhone%20Simulator/5.0/Applications/CEDB9019-1D64-4968-9BE7-57E1493B96EC/Documents/Port.sqlite)"
), NSUnderlyingError=0x7195a50 "The operation couldn’t be completed. (Cocoa error 4.)", NSFilePath=/Users/.../Library/Application Support/iPhone Simulator/5.0/Applications/CEDB9019-1D64-4968-9BE7-57E1493B96EC/Documents/Port.sqlite
只有在运行重置功能时才会出现错误。我认为设置:
self.managedObjectContext = nil;
self.managedObjectModel = nil;
self.persistentStoreCoordinator = nil;
...会解决问题的。然后一切都会重新创建。请帮忙。
非常感谢您的回答。现在没有错误,但如果我运行重置,则不会存储任何内容。保存后我立即进行提取
if (![managedObjectContext save:&error])
NSLog(@"Error while saving %@", error);
return FALSE;
CoreDataPortService *c = [[CoreDataPortService alloc] init];
NSLog(@"Saved all.... got number of ports ... %d", [[c getPorts] count]);
如果不运行我的重置方法,一切都会按预期工作。有什么问题?
【问题讨论】:
我认为重点是您想删除所有数据。不?如果删除文件,并删除内存中的 managedObjectContext,数据就消失了。如果您尝试删除文件并从内存内容中重新创建它,那么您将需要一种不同的方法。我真的无法想象你为什么要这样做。在正常情况下,持久存储将与托管对象上下文中的内容保持同步。 我想删除数据。是否也可以删除文件。那是因为有时我会更改实体。 你说,“如果我运行我的重置,什么都不会被存储”。听起来您不想存储任何内容,即删除所有内容。你的意思是你运行reset,然后添加对象,然后保存,之后就没有对象了吗? 很抱歉让您感到困惑。当我运行重置时,我想删除所有内容。删除所有内容后,我想再次解析我的 xml 并存储对象的状态。所以存储我的 XML 的状态我以前没有运行我的重置。所以 1. 重置所有对象(删除 XML) 2. 解析新的 XML 并存储它。第2步现在是我的问题。如果我之前没有运行第 1 步,第 2 步有效。 【参考方案1】:您为 managedObjectContext 编写了一个 setter,但它什么也没做:
- (void) setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
当您调用self.managedObjectContext = nil
时,它所做的只是调用[self setManagedObjectContext:nil]
。那没有任何作用。实例变量 managedObjectContext 保持相同的值,当您再次使用 getter 请求它时,您仍然拥有与已删除文件关联的 managedObjectContext。你需要:
- (void) setManagedObjectContext:(NSManagedObjectContext *)_managedObjectContext
[managedObjectContext release];
managedObjectContext = _managedObjectContext;
[managedObjectContext retain];
这也是假设你的 managedObjectContext 属性是用 nonatomic 修饰符声明的。如果它被声明为原子的,您还需要代码来锁定。以类似的方式编写 managedObjectModel 和 persistentStoreCoordinator 的 setter。
@synthesize 通常会为您生成类似的 setter,但是由于您想编写自己的 getter,因此您也必须编写自己的 setter。可能有一种方法可以让 @synthesize 只为您的属性创建设置器,但我不记得了。
回答后续问题。也许你正在做这样的事情:
NSManagedObjectContext *moc = self.managedObjectContext;
[self reset];
[self repopulateData:xmlFile];
NSError *error = nil;
if (![moc save:&error])
[self logError:error];
如果是这种情况,那么您将在旧的托管对象上下文中调用 save。不知道那会是什么结果。而是将倒数第二行更改为
if (![self.managedObjectContext save:&error])
确保您使用的是当前托管对象上下文。
或者类似地,您可能正试图从旧的托管对象上下文中读取。检查您正在使用的任何托管对象上下文指针的地址,并确保它们指向与您在重置中创建的新托管对象上下文相同的东西。
如果这不是问题,我不知道。您将不得不尝试收集更多关于它为什么不起作用的信息。例如,该文件是否存在?添加数据时它的大小会增加吗?数据是否写入文件,但无法读取?
【讨论】:
小问题。如果您想要自定义 getter,您也必须编写自定义设置器(反之亦然),这是不正确的。如果所需的方法不存在,@sythesize 会创建它,如果存在,它会使用该方法。你可以随意混搭。 好的,那是一个更好的答案。删除-(void)setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
并添加@synthesize managedObjectContext
。
非常感谢您的回答。
@user87444 -- 如果此答案解决了您的问题,请点击旁边的复选标记,以便显示为已回答。
好吧,错误消失了,但必须做一些其他事情才能保存。以上是关于删除以前的 sqlite 存储文件后重新创建持久性存储的主要内容,如果未能解决你的问题,请参考以下文章
XCode 4.3 无法加载持久存储 UserDictionary.sqlite
Android学习之基础知识九 — 数据存储(持久化技术)之SQLite数据库存储