删除以前的 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

Core Data SQLite 存储在更新后变为只读

Android学习之基础知识九 — 数据存储(持久化技术)之SQLite数据库存储

我应该如何命名可导入的.sqlite持久存储?

如何获取存储在 iOS 持久性 sqlite 数据库中的值?

阿里云的OSS对象存储