删除以前的sqlite存储文件后重新创建持久性存储

时间:2011-09-16 07:34:44

标签: core-data ios-4.2

我想删除我的sql lite文件并再次设置persistance存储。

//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]);

我如果不运行我的重置方法,一切都按预期工作。什么可能是错的?

1 个答案:

答案 0 :(得分:0)

您为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属性是使用非原子修饰符声明的。如果它被声明为原子,你还需要锁定代码。以类似的方式为managedObjectModel和persistentStoreCoordinator编写setter。

@synthesize通常为你生成这样的setter,但是既然你想编写自己的getter,你也必须编写自己的setter。可能有办法让@synthesize只为你的属性制作一个setter,但我不记得了。

回答问题。也许你正在做这样的事情:

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])

确保使用当前的托管对象上下文。

或者类似地,您可能尝试从旧的托管对象上下文中读取。检查您正在使用的任何托管对象上下文指针的地址,并确保它们指向与您在重置时创建的新托管对象上下文相同的内容。

如果那不是问题,我不知道。您将不得不尝试收集有关它无法正常工作的更多信息。例如,该文件是否存在?添加数据时其大小是否会增加?是将数据写入文件,但无法读取?