views:

329

answers:

1

Hi there,

I'm trying to write two applications (iphone and desktop) to achieve what's been described in the following link:

core-data-is-it-possible-to-build-a-desktop-app-to-create-the-data-model-for-an

Ok. So I've created a very simple desktop app the has a single entity named Client with a string attribute field called name. I've also generated the corresponding Model class.

I've run the app added a couple of client names to the list and saved the file (as Testing.sqlite).

Now in my equivalent iphone app I'm attempting to load the file. I've generated the app initially using one of the application templates and included Core Data. NB: I've mirrored the Client entity and generated the corresponding Model class.

I've gone into my "application delegate" class and amended the persistentStoreCoordinator method to reference my "Testing.sqlite" file i.e.

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Testing.sqlite"]];

I've also copied the saved desktop app file into the expected location i.e.

~/Library/Application Support/IPhone Simulator/User/... etc.

So now in theory at least each of the two apps should be the same.

However when I'm attempting to load the data from the it always seems to be empty. My code looks a little like this:

    // fetch the delegate.
TestingAppDelegate *app = (TestingAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = [app managedObjectContext];

// construct the request.
NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Client" inManagedObjectContext:managedObjectContext]; 
[request setEntity:entity]; 

// execute the request.
NSError *error;
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];

if (results == nil) { 
 // Handle the error.   
 NSLog(@"No data loaded");
} 

NSLog(@"Returned: %@", results); 

// finally release 
[results release]; 
[request release];

I can't seem to figure out what's going wrong. Any tips or suggestions would be totally appreciated.

When I've looked at the instance of the persistanceStoreCoordinator, managedObjectContext, resulting array (NSArray) whilst debugging I can see that it seems to contain 0 records for all of these. So I'm confused.

NB: The Testing.sqlite file contains entries.

Thanks in advance, Matt

A: 

Simply copying the sqlite database file will not work when using Core Data. You need to fully replicate the persistent store you created in your desktop application.

However, this may be a problem related to the fact that Core Data is not seeing your database file even though you copied it. Try the following:

1) add your database file to your project in the resources group 2) use this method to actually copy your database file in place

- (NSString *) initialize_db {
    NSString *DATABASE_RESOURCE_NAME = @"testing";
    NSString *DATABASE_RESOURCE_TYPE = @"sqlite";
    NSString *DATABASE_FILE_NAME = @"testing.sqlite";

    // copy the database from the bundle if necessary
    // look to see if DB is in known location (~/Documents/$DATABASE_FILE_NAME)


    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentFolderPath = [searchPaths objectAtIndex: 0];
        NSString *dbFilePath = [documentFolderPath stringByAppendingPathComponent: DATABASE_FILE_NAME];
        [dbFilePath retain];

        if (! [[NSFileManager defaultManager] fileExistsAtPath: dbFilePath]) {
         // didn't find db, need to copy
         NSString *backupDbPath = [[NSBundle mainBundle]
                 pathForResource:DATABASE_RESOURCE_NAME
                 ofType:DATABASE_RESOURCE_TYPE];
         if (backupDbPath == nil) {
          // couldn't find backup db to copy, bail
          NSLog (@"couldn't init db");
          return NULL;
         } else {
          BOOL copiedBackupDb = [[NSFileManager defaultManager]
                  copyItemAtPath:backupDbPath
                  toPath:dbFilePath
                  error:nil];
          if (! copiedBackupDb) {
           // copying backup db failed, bail
           NSLog (@"couldn't init db");
           return NULL;
          }
         }
        }


        return dbFilePath;

    }

Once you have copied the database file, you have its file path returned, and you use it to actually open the database.

unforgiven
Thanks for that code! Very useful. However I'm still unsure what you mean by "fully replicate the persistent store"? My xcdatamodel file and associated classes in my iphone app are the same as my mac app.What other steps do I need to take?
Sway
It turned out that they were subtly different. After correcting this it worked a treat. Thanks again for your help.
Sway