How to force coredata to rebuild sqlite database model?

后端 未结 3 1524
野性不改
野性不改 2020-12-23 10:37

In my app I sometimes need to rebuild and repopulate database file. SQLite databse is created and managed by CoreData stack.

What I\'m trying to do is drop the file

相关标签:
3条回答
  • 2020-12-23 11:14

    You can keep a "clean" copy of your sqlite database as part of the application bundle, then just copy over the version in the documents directory whenever you'd like to refresh the database.

    Here's some code from an App that does something similar (although this version will not copy over and existing db):

    // Check for the existence of the seed database
    // Get the path to the documents directory and append the databaseName
    NSString* databasePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: kDatabaseName];
    
    NSFileManager* fileManager = [NSFileManager defaultManager];
    if ( ![fileManager fileExistsAtPath: databasePath] ) 
    {
        NSString* databasePathFromApp = [[[NSBundle mainBundle] resourcePath] 
                                         stringByAppendingPathComponent: kDatabaseName];
    
        [fileManager copyItemAtPath: databasePathFromApp 
                             toPath: databasePath 
                              error: nil];
    }
    [fileManager release];
    
    0 讨论(0)
  • 2020-12-23 11:23

    The Core Data stack does not like you removing the file under it. If you are wanting to delete the file you should tear down the stack, delete the file and then reconstruct the stack. That will eliminate the issue.

    Part of the problem is that the stack keeps a cache of the data that is in the file. When you remove the file you don't have a way to clear that cache and you are then putting Core Data into an unknown and unstable state.

    You can try telling the NSPersistentStoreCoordinator you are removing the file with a call to -removePersistentStore:error: and then adding the new store with a call to -addPersistentStoreWithType:configuration:URL:options:error:. I am doing that currently in ZSync and it works just fine.

    0 讨论(0)
  • 2020-12-23 11:37

    I use the following method -resetApplicationModel in my app delegate and it works fine for me.

    You may not need the kApplicationIsFirstTimeRunKey user default, but I use it to test whether to populate the Core Data store with default settings in a custom method called -setupModelDefaults, which I also call from -applicationDidFinishLaunching: if the first-time run flag is YES.

    - (BOOL) resetApplicationModel {
    
        // ----------------------
        // This method removes all traces of the Core Data store and then resets the application defaults
        // ----------------------
    
        [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:kApplicationIsFirstTimeRunKey];
        NSLog(@"Turned ON the first-time run flag...");
    
        NSError *_error = nil;
        NSURL *_storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"MyAppSQLStore.sqlite"]];
        NSPersistentStore *_store = [persistentStoreCoordinator persistentStoreForURL:_storeURL];
    
        //
        // Remove the SQL store and the file associated with it
        //
        if ([persistentStoreCoordinator removePersistentStore:_store error:&_error]) {
            [[NSFileManager defaultManager] removeItemAtPath:_storeURL.path error:&_error];
        }
    
        if (_error) {
            NSLog(@"Failed to remove persistent store: %@", [_error localizedDescription]);
            NSArray *_detailedErrors = [[_error userInfo] objectForKey:NSDetailedErrorsKey];
            if (_detailedErrors != nil && [_detailedErrors count] > 0) {
                for (NSError *_detailedError in _detailedErrors) {
                    NSLog(@" DetailedError: %@", [_detailedError userInfo]);
                }                
            }
            else {
                NSLog(@" %@", [_error userInfo]);
            }
            return NO;
        }
    
        [persistentStoreCoordinator release], persistentStoreCoordinator = nil;
        [managedObjectContext release], managedObjectContext = nil;
    
        //
        // Rebuild the application's managed object context
        //
        [self managedObjectContext];
    
        //
        // Repopulate Core Data defaults
        //
        [self setupModelDefaults];
    
        return YES;
    }
    
    0 讨论(0)
提交回复
热议问题