Reputation: 936
I have 2 apps, one free, one paid for. I have the two apps set up so that people can transfer their data from the free to the paid using the following code
In the free one (in a view controller)
- (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];
}
and in the paid for one (in the app delegate)
- (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;
}
Now this code works, but i have to close the app and restart it to get the new core data to load. How do i make it so that you don't have to close and reopen the app to show the new data, i've tried using a reload data on the table but it still shows the old records
I think the problem comes from the fact the handleOpenURL method is called after the persistentstore is already set up
New code in the openurl method
__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);
Upvotes: 0
Views: 355
Reputation: 70956
This happens because of how files work on Unix (and therefore on iOS). Once a file is open, removing it (including by overwriting it) doesn't actually remove the file until all open file handles to it are closed. So, you keep accessing the same file until you close the app, which closes the file handle. On the next run you get the new version.
If possible, the easy way to deal with this is to not create your persistence stack until after overwriting the store file. That might not be easy or possible though. In that case you can close the existing store file by getting rid of the NSPersistentStore
that references it. That will mean completely tearing down the existing persistence stack and starting over. That means getting rid of every instance of NSPersistentStoreCoordinator
, NSManagedObjectContext
, and NSManagedObject
. Then go back and build the stack up again just like when the app launched. (You could keep the NSPersistentStoreCoordinator
if you called removePersistentStore:error:
for the old version and then added the new one, but it doesn't really simplify the process).
Upvotes: 3
Reputation: 394
Try in your handleOpenURL method to set the managedObjectContext, managedObjectModel and persistentStoreCoordinator to nil. That should force the app to reload the db file the next time CoreData is used to access data.
Upvotes: 0