覆盖核心数据文件,然后加载新文件

时间:2013-07-10 17:34:21

标签: ios core-data

我有2个应用,一个免费,一个付费。 我设置了两个应用程序,以便人们可以使用以下代码将数据从免费转移到付费

在免费的(在视图控制器中)

- (IBAction)exportToPro:(id)sender
{
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Medicine_Tracker.sqlite"];
    NSString *storeURLString = [storeURL path];

    if( [[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]] ) NSLog(@"Exists");

    NSData *fileData = [NSData dataWithContentsOfFile:storeURLString];
    NSString *encodedString = [GTMBase64 stringByWebSafeEncodingData:fileData padded:YES];
    NSString *urlString = [NSString stringWithFormat:@"mt://localhost/importDatabase?%@", encodedString];
    NSURL *openURL = [NSURL URLWithString:urlString];
    [[UIApplication sharedApplication] openURL:openURL];
}

和付费的一个(在应用代表中)

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    if([@"/importDatabase" isEqual:[url path]]) {
        NSString *query = [url query];
        NSData *importUrlData = [GTMBase64 webSafeDecodeString:query];

        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Medicine_Tracker.sqlite"];
        NSString *storeURLString = [storeURL path];
        if( [[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]] ) NSLog(@"Exists");

        // NOTE: In practice you will want to prompt the user to confirm before you overwrite their files!
        [importUrlData writeToFile:storeURLString atomically:YES];
        return YES;
    }
    return NO;
}

现在这段代码可以运行了,但我必须关闭应用程序并重新启动才能获取要加载的新核心数据。如何制作它,以便您不必关闭并重新打开应用程序以显示新数据,我已尝试在表格上使用重新加载数据,但它仍显示旧记录

我认为问题来自于在已经设置了persistentstore之后调用handleOpenURL方法的事实

openurl方法中的新代码

__persistentStoreCoordinator = nil;
        __managedObjectContext = nil;
        __managedObjectModel = nil;

        NSLog(@"PSC: %@ - MOC: %@ - MOM: %@", __persistentStoreCoordinator, __managedObjectContext, __managedObjectModel);

        NSError *error = nil;
        __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

        if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {

            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        }

        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Medicine_Tracker" withExtension:@"momd"];
        __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if (coordinator != nil) {
            __managedObjectContext = [[NSManagedObjectContext alloc] init];
            [__managedObjectContext setPersistentStoreCoordinator:coordinator];
        }

        NSLog(@"PSC: %@", __persistentStoreCoordinator);
        NSLog(@"MOC: %@", __managedObjectContext);
        NSLog(@"MOM: %@", __managedObjectModel);

2 个答案:

答案 0 :(得分:3)

这是因为文件在Unix上(因此在iOS上)的工作方式。一旦文件打开,删除它(包括通过覆盖它)实际上不会删除文件,直到关闭它的所有打开文件句柄。因此,在关闭应用程序之前,您将继续访问同一文件,从而关闭文件句柄。在下一次运行中,您将获得新版本。

如果可能,处理此问题的简单方法是在覆盖存储文件之前不要创建持久性堆栈。但这可能并不容易或不可能。在这种情况下,您可以通过删除引用它的NSPersistentStore来关闭现有的商店文件。这将意味着彻底拆除现有的持久性堆栈并重新开始。这意味着摆脱NSPersistentStoreCoordinatorNSManagedObjectContextNSManagedObject的每个实例。然后返回并再次构建堆栈,就像应用程序启动时一样。 (如果您为旧版本调用NSPersistentStoreCoordinator然后添加新版本,则可以保留removePersistentStore:error:,但这并不能简化该过程。

答案 1 :(得分:0)

尝试使用handleOpenURL方法将managedObjectContext,managedObjectModel和persistentStoreCoordinator设置为nil。这应该会强制应用程序在下次使用CoreData访问数据时重新加载db文件。