Search code examples
objective-cmacossqlitecocoaosx-yosemite

How to copy database file in Application Support directory in Cocoa without losing data?


I have tried this code but it creates BLANK database.sqlite file in document directory.

- (void)createEditableCopyOfDatabaseIfNeeded
{
    // First, test for existence.
    BOOL success;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"prediction.sqlite"];



    success = [fileManager fileExistsAtPath:writableDBPath];

    if (success) return;
    // The writable database does not exist, so copy the default to the appropriate location.
    NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"prediction.sqlite"];

    success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];


    if (!success) {
        NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);

    }
}

How do I ensure that when I copy database file it does not create an empty database?

Any help would be greatly appreciated.


Solution

  • First your code were not attempts to create a database file.

    So... You just want to copy the database file “prediction.sqlite” from source bundle to UserDomain dir? If this is your purpose,You should pay attention to the code:

      if (success) return;
    // The writable database does not exist, so copy the default to the appropriate location.
    

    The correct should be:

          if (!success) return;
    // The writable database does not exist, so copy the default to the appropriate location.
    

    The directories returned by NSSearchPathForDirectoriesInDomains are not guaranteed to exist; you need to create them yourself, if necessary (see the documentation). NSFileManager's createDirectoryAtPath:withIntermediateDirectories:attributes:error: can help with that.@Anomie

    try those code:(before you copy the "prediction.sqlite" file, you need add the file in to your project bundle.): enter image description here

    - (void)createEditableCopyOfDatabaseIfNeeded
    {
        // First, test for existence.
        BOOL success;
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSError *error;
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
    
        NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"prediction.sqlite"];
    
        success = [fileManager fileExistsAtPath:writableDBPath];
    
        if (!success){
            // create the directories, because the directories returned by NSSearchPathForDirectoriesInDomains are not guaranteed to exist
            if (![fileManager createFileAtPath:writableDBPath contents:nil attributes:nil]) {
                return;
            }
        }
    
        // The writable database does not exist, so copy the default to the appropriate location.
        NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"prediction.sqlite"];
    
        // remove the same file, before you copy the file
        [fileManager removeItemAtPath:writableDBPath error:nil];
    
        success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
    
        if (!success) {
            NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
    
        }
    }