Running the App on the iPhone works fine, but only if it stays connected to the Mac/linked to Xcode.
If I try to run it after I disconnected it (after stopping the Run), Core Data does not work anymore. Neither the Build nor the Debug configuration works (Product -> Edit scheme... -> Run xy.app -> Info -> Build configuration).
My xcdatamodel settings:
File Type: Default Core Data Model
Location: Relative to Group
Any ideas?
Cheers,
Saeppi
Sorry for not being more specific about my issue. There's no crash, the changes I thought I did to the Core Data Model just did not happen.
Reading a bit more about SQLite and how it works with Core Data, I admit that I committed a very stupid error: I copied the *.sqlite file from a tutorial and imported it into my Xcode project and copied it to the App's folder (and then renaming it of course). Removing the sqlite file causes now the following error:
error: /Users/myName/Documents/myApp/myApp.sqlite: No such file or directory
My PersistentStoreCoordinator:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"MyApp.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"ErrorKey", nil)
message:NSLocalizedString(#"ErrorDBKey", nil)
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
return persistentStoreCoordinator;
}
and my application's directory:
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
I thought Core Data would generate a new sqlite file once it's been removed from the folder. What's the error in reasoning?
Does it crash on device?
You can connect the device and check the crash report in device logs.It will give you better idea about what is happening.Secondly try to quit app from background and run.
I would suggest check the crash logs on device, if it's not able to create or find the core data it will give a message like: store missing or something like that.
Most likely you are opening your db file in the main bundle. Main bundle is read only. Your db file needed to be in the app's document folder.
Checkout this SO post
Related
I am using encrypted-core-data to encrypts all data that is persisted , previously simple CoreData was using. persistentStoreCoordinator creation code are as follows .
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *oldStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"VistaJetApp.sqlite"];
NSURL *newStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"VistaJet.sqlite"];
NSError *error = nil;
NSString *currentPassword = [[VJAesCryptoWrapper getInstance] getCurrentPassword];
NSDictionary *options = [self getEncryptedStoreOptionsWithPassword:currentPassword andDatabaseStore:newStoreURL];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
//if old store not exists , it means fresh installation
if([[NSFileManager defaultManager] fileExistsAtPath:oldStoreURL.path] == NO) {
if (![_persistentStoreCoordinator addPersistentStoreWithType:EncryptedStoreType configuration:nil URL:newStoreURL options:options error: &error]) {
}
} else {
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:oldStoreURL options:#{NSMigratePersistentStoresAutomaticallyOption:#YES, NSInferMappingModelAutomaticallyOption:#YES} error: &error]) {
}
NSPersistentStore *oldUnsecureStore = [_persistentStoreCoordinator persistentStoreForURL:oldStoreURL];
[ConsoleLogger logText:[NSString stringWithFormat:#"Migration started"]];
//start migration
if(![_persistentStoreCoordinator migratePersistentStore:oldUnsecureStore toURL:newStoreURL options:options withType:EncryptedStoreType error:&error]) {
} else {
[[NSFileManager defaultManager] removeItemAtURL:oldStoreURL error:nil];
}
}
return _persistentStoreCoordinator;
}
Creation of options dictionary
- (NSDictionary*)getEncryptedStoreOptionsWithPassword:(NSString*)password andDatabaseStore:(NSURL*)storeUrl {
return #{ EncryptedStorePassphraseKey: password,
EncryptedStoreDatabaseLocation: storeUrl,
NSMigratePersistentStoresAutomaticallyOption:#YES,
NSInferMappingModelAutomaticallyOption:#YES
};
}
I am saving password in keychain using KeychainItemWrapper and my code crashing exactly on getEncryptedStoreOptionsWithPassword:currentPassword method. App is live and I am not able to reproduce the crash , but on crashlytics it is showing so many crashes
crashlytics crash logs image
Also using AESCrypt to encrypt password then saving it to keychain using KeychainItemWrapper.
Observation:
The crash that crashlytics is displaying only appear when we upload build on test flight using distribution profile.
crash is happening 100% on iOS 11 as reported by crashlytics
I think this is a known bug in iOS 10 that you are seeing, there is a work-around: enable "Keychain Sharing" (under your app -> Capabilities tab in Xcode).
KeychainItemWrapper crash on iOS10
I recently updated from xcode 3.x to 4.2 and I am having issues with core data when I run apps in 4.2. I also updated to iOS 5 so maybe the issue is in there, I'm not really sure.
The apps ran fine in 3.x but crash in 4.2. The issue occurs whenever I tried to access a NSPersistentStoreCoordinator object. Here is an example of an area where the app crashes.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator_ != nil) {
return persistentStoreCoordinator_;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"GraffitiMap.sqlite"];
NSError *error = nil;
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator_;
}
It cashes at the line: persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
What am I missing about transitioning an app from xcode 3.x to 4.2, or upgrading to iOS 5?
I met with this problem before after I upgraded to Xcode 4.2 and iOS 5.
My app was keeping crash on [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; with error EXEC_BAD_ACCESS, I did a lot of tests to investigate where the problem is. Finally after I deleted all fetch requests in data model, the error gone and said another error "the entity name not found". So I was trying to delete fetch request one by one, and test again and again to figure out which is that "bad" fetch request. And I found that there are two fetch requests do same thing (have same criteria on same entity) although they have different name, than I deleted one of them, the error was fixed completely.
Today I meet with this problem again, and I'm sure that there is no duplicate fetch request this time, but the error still remain. I thought apple add some validations on CoreData like this in new iOS5, but can not find any docs which describe this.
Hope this help you
In My Application
I have one sqlite file CoreDataBountyHunter.sqlite
I am using the Core Data Object Model to connect this sqlite file.
As it is the Basic application I have got the error before fetching the data or actual code part. I have got the error like Persistent store coordinator can not connect to file or Model.
1) visits the view will appear part
NSManagedObjectContext *moc=appDelegate.managedObjectContext. Part
from that it goes to the
2) Some code which shows File is Exists
3) then it goes to the Below code of persistent store coordinator from which it calls the Function of MANAGED OBJECT MODEL which is present at next code here...
After returning back to persistent coordinator in if condition it has got error and aborting so please help
-
//1--------
(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSURL *storeURL=[[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"CoreDataBountyHunter.sqlite"];
NSLog(#"%#",storeURL);
NSError *error = nil;
**__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])**
{
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
Check the error message to determine what the actual problem was.
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
**abort();** I have error at this place
} ``
return __persistentStoreCoordinator;
}
enter code here
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil)
{
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"CoreDataBountyHunter" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
//-------------------------------------------------------------------------------------
Actually it is a total mess with how Core data is working with different paths to read Write data so please explain also. Thanks Why I am getting the error at this place.
So, After visiting the MANAGED OBJECT MODEL CODE IT GOES TO THE PERSISTENT COORDINATOR SO AT THIS PLACE IT SHOULD HAVE SOME MESS...
Any time If you change the .xcdamodel file then your application will crash surely.
Can you try to this code in core data:
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}
No need to shout...
What happens when you use the more usual
+ (NSManagedObjectModel *)mergedModelFromBundles:(NSArray *)bundles
as in
- (NSManagedObjectModel *)managedObjectModel
{
if (!__managedObjectModel)
{
__managedObjectModel = [[NSManagedObjectModel mergedModelFromBundle:nil] retain];
}
return __managedObjectModel;
}
Unless you have multiple models it's slightly cleaner
A suggestion:
Whenever you want to make changes in the core data file then don' do it directly in the same file or version of core data. Best practice is to follow the Modal versions for core data. It will prevent the crashes and also It will be very helpful in case when your app is already in production.
For modal version, refer this link. For more description please research on Google.
https://developer.apple.com/library/ios/recipes/xcode_help-core_data_modeling_tool/Articles/creating_new_version.html
I get an annoyingly vague error from the following code:
GFree2AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
context = [delegate managedObjectContext];
context is defined as a NSManagedObjectContext in the .h file and is the same in the delegate. All the right files seem to be included (except for <CoreData/CoreData.h> in the .m file - but the program throws the same issue whether its included or not. Its included in the header file.)
All the correct frameworks and stuff are included - when I started the project I selected "use coredata to manage data" or whatever it was. So surely there shouldn't be a problem?
Is there a better way to do what I'm trying to do? Basically I don't want to have to keep passing the context through different classes till I eventually want to use it (storing data is such a small part of my application).
In the console the error I get is:
2010-08-28 13:09:24.726 GFree2[3912:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter'
...
terminate called after throwing an instance of 'NSException'
Program received signal: “SIGABRT”.
If I comment out the line: context = [delegate managedObjectContext]; then it all seems to work fine. (at the moment I haven't acctually used any coredata or anything so theres no more code related to it.
Thanks for anyone who can help, or provide some insight into this - its so complicated.
Edit: my app delegate file methods:
#pragma mark -
#pragma mark Core Data stack
/**
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;
}
NSString *modelPath = [[NSBundle mainBundle] pathForResource:#"GFree" ofType:#"momd"];
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
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 = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"GFree.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
Check the error message to determine what the actual problem was.
If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
* Simply deleting the existing store:
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
* Performing automatic lightweight migration by passing the following dictionary as the options parameter:
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
#pragma mark -
#pragma mark Application's Documents directory
/**
Returns the path to the application's Documents directory.
*/
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
EDIT AGAIN:
NSString *modelPath = [[NSBundle mainBundle] pathForResource:#"GFree" ofType:#"momd"];
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
is the line where the error is. I'm not sure what type of file this is, but I'm sure it's obviously not finding it or something... :/ any ideas what I'm supposed to do?
#kiamlaluno - sorry for rolling back your edits, didn't mean to, just curious to see what you'd changed and thought that would show me... but it just completely removed them apparently. lol.
Edit build results:
DataModelCompile build/Debug-iphonesimulator/GFree2.app/GFree2.mom GFree2.xcdatamodel
cd "/Volumes/files/Gluten Free Cooking/Tom iPhone App/GFree2"
setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Developer/usr/bin/momc -XD_MOMC_TARGET_VERSION=10.6 "/Volumes/files/Gluten Free Cooking/Tom iPhone App/GFree2/GFree2.xcdatamodel" "/Volumes/files/Gluten Free Cooking/Tom iPhone App/GFree2/build/Debug-iphonesimulator/GFree2.app/GFree2.mom"
I believe that the problem is in persistentStoreCoordinator method in your GFree2AppDelegate.m file.
Could you update your question with the exact code of managedObjectModel, managedObjectContext and persistentStoreCoordinator methods from this file?
These methods are generated by the XCode when you check "Use Core Data for storage".
By the way, you shouldn't import .m files.
You're getting the error because GFree.momd doesn't exist. From the docs for NSURL's pathForResource:ofType: method:
Return Value The full pathname for the resource file or nil if the file could not be located.
GFree.momd is generated at build time from your .xcdatamodeld file (look in the Build Results for the line starting DataModelVersionCompile and expand it). Have you deleted or renamed that file?
Is it still listed in the Compile Sources section of your build target? (In Xcode expand Targets / [AppName] / Compile Sources).
Just noticed that your debug log says the app is called GFree2 but your code's looking for GFree.momd. Did you rename the project? If the data model file is now called GFree2.xcdatamodeld then you need to change the line that imports the momd file to use the new GFree2 name, too.
Folks,
Lightweight migration is failing for me 100% of the time on this line:
[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]
with the error:
Error: Error Domain=NSCocoaErrorDomain Code=134130 UserInfo=0x4fbff20 "Operation could not be completed. (Cocoa error 134130.)"
"Can't find model for source store";
Here is my managed object context, model, and persistent store:
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"Locations.sqlite"]];
NSError *error;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
// Allow inferred migration from the original version of the application.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
NSLog(#"Error: %#",error);
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
I have two versions of my model in my project: a version 4 and a version 5. If I set my version 4 as default, it works fine. If I select "Design -> Data Model -> Add Model Version" (as described by this post), make a change, Design -> Data Model -> Set Current Version, build and run, it will fail with the aforementioned "Can't find model for source store" error. Set model back to version 4, no problems, addPersistentStoreWithType. Alternatively, if I add model version and make no changes, simply go from version 4 to 5 without adding any new fields, no problems. If I then try to go from 5 to 6, the aforementioned error.
This code is failing on both Simulator and Phone. I read several prescriptions calling for deleting and reinstalling the app, which does work for both Simulator and Phone, but I am afraid that when I release this to real users it will break my installed base since they won't be able to delete and reinstall - App Store will auto-upgrade them.
This code worked in releases past with no changes on my part - hence my ability to make it all the way up to version 4. I recently upgraded to XCode 3.2.3 building for iOS4, which may have something to do with this.
Is anyone else having this issue all of a sudden now like I am? Has anyone managed to work past it? Thanks.
PS - For Googlers who stumble on this page, here are all the relevant pages you might consider reading, below. Unfortunately none of these solved my issue.
Implementation of "Automatic Lightweight Migration" for Core Data (iPhone)
http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html
https://stackoverflow.com/questions/2925918/iphone-core-data-lightweight-migration-error-reason-cant-find-model-for-sour
iPhone Core Data "Automatic Lightweight Migration"
http://www.iphonedevsdk.com/forum/iphone-sdk-development/38545-coredata-migration-issues.html
UPDATE
While this is not a real fix, it does avoid the scenario of a crashing client: simply delete the database file:
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Delete file
if ([[NSFileManager defaultManager] fileExistsAtPath:storeUrl.path]) {
if (![[NSFileManager defaultManager] removeItemAtPath:storeUrl.path error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error])
{
// Handle the error.
NSLog(#"Error: %#",error);
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
UPDATE 2
Here is what happens when I inspect VersionInfo.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSManagedObjectModel_CurrentVersionName</key>
<string>Profile 5</string>
<key>NSManagedObjectModel_VersionHashes</key>
<dict>
<key>Profile</key>
<dict>
<key>Profile</key>
<data>
ZIICGgMBreuldkPXgXUhJwKamgwJzESM5FRTOUskomw=
</data>
</dict>
<key>Profile 2</key>
<dict>
<key>Profile</key>
<data>
tEB7HrETWOSUuoeDonJKLXzsxixv8ALHOoASQDUIZMA=
</data>
</dict>
<key>Profile 3</key>
<dict>
<key>Profile</key>
<data>
qyXOJyKkfQ8hdt9gcdFs7SxKmZ1JYrsXvKbtFQTTna8=
</data>
</dict>
<key>Profile 4</key>
<dict>
<key>Profile</key>
<data>
lyWDJJ0kGcs/pUOModd3Q1ymDvdRiNXui4NCpLxDFSw=
</data>
</dict>
<key>Profile 5</key>
<dict>
<key>Profile</key>
<data>
V4PyRK1ezj3xK1QFRCTVzGOqyJhEb7FRMzglrTsP0cI=
</data>
</dict>
</dict>
</dict>
</plist>
Here is the code that I wrote to inspect my model (note I had to go out and add a base64 encoder, since that is what is in the VersionInfo.plist file)
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeUrl error:&error];
NSLog(#"%#",storeMeta);
id someObj = [[storeMeta objectForKey:#"NSStoreModelVersionHashes"] objectForKey:#"Profile"];
NSLog(#"%#",someObj);
NSLog(#"%#",[NSString base64StringFromData:someObj length:[someObj length]]);
And here is the debug output:
{
NSPersistenceFrameworkVersion = 310;
NSStoreModelVersionHashes = {
Profile = <97258324 9d2419cb 3fa5438c a1d77743 5ca60ef7 5188d5ee 8b8342a4 bc43152c>;
SerializedMessage = <4530863c d943479a edfb4dfb 5059c28d d6137dc4 d1153d36 ed52be49 11074f13>;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
);
NSStoreType = SQLite;
NSStoreUUID = "823FD306-696F-4A0F-8311-2792825DC66E";
"_NSAutoVacuumLevel" = 2;
}
<97258324 9d2419cb 3fa5438c a1d77743 5ca60ef7 5188d5ee 8b8342a4 bc43152c>
lyWDJJ0kGcs/pUOModd3Q1ymDvdRiNXui4NCpLxDFSw=
As you can see, that last line that starts with 'ly' matches Profile 4 in VersionInfo.plist...hence I see no reason why it should be failing. Any other ideas?
I read several prescriptions calling
for deleting and reinstalling the app,
which does work for both Simulator and
Phone, but I am afraid that when I
release this to real users it will
break my installed base since they
won't be able to delete and reinstall.
This is a problem caused by Xcode not removing old momc files from simulator/dev-device when a the model file is changed e.g. changing the name. The old file remains which causes confusion. This is something you only see during development because it is an artifact of the way that Xcode manipulates the app bundle without completely reinstalling it every time as must happen with a release version.
You can confirm this logging the return of:
[[NSBundle mainBundle] URLsForResourcesWithExtension:#"momc"subdirectory:nil];
... which should show you all the compiled model files in the app bundle
It is bad practice to rely on migration during development because it is very common for migration to fail if you are making changes to the model and store. You should only use migration after all the code is nailed down. I would also recommend regenerating your store from scratch every time you run. It is to easy to build up garbage in the store by changing up the model.
I've read over your updated question. It's getting quite messy with model versions.
You should try and audit the version of the model that the existing store is actually asking for, and try to list all available models in the app bundle at runtime.
I look in my apps' model directory
NSString *modelDirectoryPath = [[NSBundle mainBundle] pathForResource:#"MyModel" ofType:#"momd"];
I'm not sure if developers normally do this, but I keep my model versions with different names.. so I have in there:
VersionInfo.plist
MyModel.mom
MyModel2.mom
The version hashes listed in the VersionInfo.plist should help you troubleshoot. Look for the version hash required by the existing persistent store, and see if you can locate it in the version hashes listed in VersionInfo.plist.
Actually, I can't see a way to write some code that will ask the persistent store what it's entity version hashes are. The NSPersistentStoreCoordinator or the NSMigrationManger seem to be doing that privately. i.e. they check the persistent store entity versions against the model that the store is loaded with.
Had another quick look, and it's available in the store meta data. Nice and easy!
NSError *error;
NSURL *storeURL = [NSURL fileURLWithPath:[[self class] storePath]];
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeURL error:&error];
And looking in storeMeta I get a key with
<CFString 0x7328050 [0x2724380]>{contents = "NSStoreModelVersionHashes"} = <CFBasicHash 0x7328340 [0x2724380]>{type = immutable dict, count = 5,
entries =>
0 : <CFString 0x7328110 [0x2724380]>{contents = "MyEntityNameOne"} = <CFData 0x73281b0 [0x2724380]>{length = 32, capacity = 32, bytes = 0x143325cf121239ce156af2e2a1aad7d9 ... 976977fdf29fc013}
1 : <CFString 0x7328130 [0x2724380]>{contents = "MyEntityNameTwo"} = <CFData 0x7328200 [0x2724380]>{length = 32, capacity = 32, bytes = 0x0ca6ecf1283d12bd3ca82af39b6b9f5d ... 149dd39a591e0c4d}
... }
Should be easy to iterate over that NSStoreModelVersionHashes dictionary and log the version hashes your store requires.
Manually match that back to the ones available in VersionInfo.plist and see what's missing. Perhaps there's not one single model that contains all the required versions of the entities in your existing persistent store. That might happen due to (accidental?) edits on the model before or after setting up a new model version?
I had esilver's exact problem and found this question via Google. However, the fix that worked for me wasn't anywhere else on SO (that I know), so here goes:
If there are multiple copies of your *.mom files (compiled object models) in your bundle, Core Data may become confused when attempting to migrate on your behalf.
Our problem was that each individual model file (Data.xcdatamodel, Data_V1.xcdatamodel, Data_V2.xcdatamodel, etc.) was not only inside the xcdatamodeld/ directory (which was included as something to compile in the build process), but also each file was also included in the "Compile Sources" list.
What this meant is that the resulting bundle had two sets of *.mom files: one inside xcdatamodeld/ and one at the top level. I think Core Data became very, very confused, and led to this error. Removing each xcdatamodel file from the "compile sources" and leaving the xcdatamodeld directory solved the problem for us (e.g. got auto-versioning up and running again). Hope this helps!
Well in my case exactly the same thing was happening and i was on iOS 7 and this problem screwed my head for at least a week and then finally find the solution which works for me
.
In order to make it work you have to add an extra value in options which is used to add PersistentStore and then you go( I am not sure about other iOS version but yeah it will definitely work on iOS 7).
-(NSManagedObjectModel *)managedObjectModel
{
if (managedObjectModel != nil)
{
return managedObjectModel;
}
managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
return managedObjectModel;
}
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (persistentStoreCoordinator != nil)
{
return persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"ABC.sqlite"];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] ini tWithManagedObjectModel:[self managedObjectModel]];
//Creating Lightweight migration.
NSDictionary *options =
#{
NSMigratePersistentStoresAutomaticallyOption:#YES
,NSInferMappingModelAutomaticallyOption:#YES
,NSSQLitePragmasOption: #{#"journal_mode": #"DELETE"}
};
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
Folks,
For the record, I ceased use of core data completely. My code was complicated and, per the issues above, unreliable. I use SQLLite directly now and am WAY happier. I cannot recommend using Core Data in any scenario.