small medium large xlarge

Back to: All Forums  Core Data
Generic-user-small
16 Jun 2010, 13:47
Greg Robertson (21 posts)

I have created a backup of my CoreData data that is sent via an encoded URL in an email. When the user clicks the link the data is parsed and read back in.

All this works fine except I would like to know what the best pattern to restore the data to the persistent store would be? I need to delete the data in the existing persistent store and replace it with the backed up data from the URL.

I could simply write a new persistent store and rename it after I have deleted the previous one. I could delete all the objects in the persistent store and write the new ones (dangerous if the data restore fails).

I think there must be a very simple solution but not sure what it is.

Thanks

Greg

Avatarsmall_pragsmall
17 Jun 2010, 00:01
Marcus S. Zarra (284 posts)

If you are doing a full replace then tearing down the Core Data stack and replacing the file would be fastest and least error prone.

Generic-user-small
18 Jun 2010, 11:46
Greg Robertson (21 posts)

Is there a formal way to do the teardown or do I simply set the MOC, MO and store to nil? Right now I am unsuccesful with this:

NSFileManager *fileManager = [NSFileManager defaultManager];
myAppDelegate *appDelegate = (myAppDelegate *)[[UIApplication sharedApplication] delegate];
          
NSArray *storeArray = [appDelegate.backupPersistentStoreCoordinator persistentStores];
NSPersistentStore *store = [storeArray objectAtIndex:0];
[appDelegate.backupPersistentStoreCoordinator removePersistentStore:store error:&error];

NSURL *originalUrl = [NSURL fileURLWithPath: [[appDelegate applicationDocumentsDirectory] stringByAppendingPathComponent: @"User.sqlite"]];
NSURL *backupUrl = [NSURL fileURLWithPath: [[appDelegate applicationDocumentsDirectory] stringByAppendingPathComponent: @"UserBackup.sqlite"]];
NSURL *resultingURL = nil;
BOOL success = NO;
success = [fileManager replaceItemAtURL:originalUrl withItemAtURL:backupUrl backupItemName:nil options:0 resultingItemURL:&resultingURL error:&error];

if (success)
{
     success = [fileManager removeItemAtURL:backupUrl error:&error];

</code>

success is always returning NO, but the error from both removal of the backup persistent store (I am not connecting to the other persistent store) and the replace both come back nil;

Any ideas how to approach this? Should I instead set the MOC, store and MO to nil?

Not sure exactly how to approach this and not much in the docs or web.

Thanks

Greg

Avatarsmall_pragsmall
18 Jun 2010, 19:58
Marcus S. Zarra (284 posts)

You want to release the three objects in the core data stack (@NSManagedObjectContext@, @NSPersistentStoreCoordinator@ and the @NSManagedObjectModel@). From there you should be able to replace the file. If you are getting a failure on the replacement then spit out the error information (both its @-localizedDescription@ and its @-userInfo@) to the console and see what the problem is.

Generic-user-small
19 Jun 2010, 02:32
Greg Robertson (21 posts)

I am getting NO as success but the error is nil so I can’t get a description of the error.

I ended up using a different approach, kept the connection and migrated the store:

NSFileManager *fileManager = [NSFileManager defaultManager];
          
myAppDelegate *appDelegate = (myAppDelegate *)[[UIApplication sharedApplication] delegate];

NSURL *originalUrl = [NSURL fileURLWithPath: [[appDelegate applicationDocumentsDirectory] stringByAppendingPathComponent: @"User.sqlite"]];
[fileManager removeItemAtURL:originalUrl error:&error];
          
NSURL *backupUrl = [NSURL fileURLWithPath: [[appDelegate applicationDocumentsDirectory] stringByAppendingPathComponent: @"UserBackup.sqlite"]];
NSArray *storeArray = [appDelegate.backupPersistentStoreCoordinator persistentStores];
NSPersistentStore *store = [storeArray objectAtIndex:0];          
store = [appDelegate.backupPersistentStoreCoordinator migratePersistentStore:store toURL:originalUrl options:nil withType:NSSQLiteStoreType error:&error];
          
if (store != nil)
{
     BOOL success = [fileManager removeItemAtURL:backupUrl error:&error];
     if (success)

</code>

Not quite as safe as the over write method but it does work.

If you could point me to a code example for how to do the overwrite I might give it another shot, or if there is a better approach, but seems like the disconnection might not be a straight forward thing.

Greg

You must be logged in to comment