Clarification on 'not accessing' sqlite DB: The context/store is not able to detect any entries in the .sqlite on devices only, despite the NSBundle having the .sqlite and the file size of the .sqlite being the correct size. In the simulator, the context/store works fine.
I'm pretty stumped on this. I added a model version to my xcdatamodeld. I reset the version, have my code to automatically do migrations, and repopulated my database.
On the iPhone simulator, it works. However, when running off a device, it fails to read from the database.
I've put in code to detect that the sqllite is actually on the device and also verify the file size. The SQLLite is being copied over correctly from the NSBundle, as well as the file size indicating there is data.
Somehow, my code is refusing to access the DB on the device. Any idea why this is? The code for accessing the DB has not changed - the only thing that changed was the datamodel. The code below was working for devices prior to the upgrade.
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"sirona" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"sirona.sqlite"];
NSString *databasePath = [NSBundle.mainBundle pathForResource:@"sirona" ofType:@"sqlite"];
NSLog(@"File manager: %@", [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[[NSBundle mainBundle] bundlePath] error:nil]);
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath: @"sirona.sqlite" error: NULL];
UInt32 result = [attrs fileSize];
NSLog(@"File size: %d", (unsigned int)result);
NSError *error = nil;
// important part starts here
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
How I'm accessing the DB through core data:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Representative" inManagedObjectContext:context]];
[request setIncludesSubentities:NO]; //Omit subentities. Default is YES (i.e. include subentities)
NSError *err;
NSUInteger count = [context countForFetchRequest:request error:&err];
NSLog(@"Count: %lu", (unsigned long)count);
Edit: Not sure how this was working without the code to copy it to the device. But it seems to be working now.
Code to do this:
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"sirona.sqlite"];
if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]]) {
NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sirona" ofType:@"sqlite"]];
NSLog(@"PreloadURL: %@", preloadURL);
NSError* err = nil;
if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURL error:&err]) {
NSLog(@"Oops, could copy preloaded data");
}
}
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];