NSManagedObjectMOdel fails to initialize on iOS 5 and above - iphone

I have a project which works fine when I build it for iOS 4.x, however it fails when I build it for iOS 5.x with a crash. To clarify, the 4.x build will run fine on iOS 5.1, however when I build against 5.0 or 5.1, I get the crash described below.
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel == nil)
{
__managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain]; //crash
}
return __managedObjectModel;
}
I checked the docs, and supposedly supplying nil as for the parameter is supposed to default to the main bundle. Anyone know if anything that changed with CoreData that would cause this to happen?
For what it's worth, I've run the "Analyze" tool and no memory leaks or anything unusual is being reported.

I've managed to come up with a work around. I created a new single-view project and then copied the generated code to initialize the managed object model into my new project. My hunch is that that [[NSManagedObjectModel mergedModelFromBundles:nil] works differently in the iOS 5.1 SDK and perhaps it wasn't able to find my data model as it wasn't stored in the project root but a separate "Data" folder.
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil)
{
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"PreferencesModel" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}

You don't actually describe the crash or provide any error messages but the following StackOverflow question has a solution to a crash that may help:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSArrayM insertObject:atIndex:]: object cannot be nil

Related

VerificationController unrecognized selector iOS 5.0.1

I just added In-App Purchasing to my iOS app and a few of my users are crashing out with
-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xf0a6f10
Obtained from BugSense, the memory location refers to the last line of this excerpt from Apple's VerificationController.m
- (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)transaction
{
if (!(transaction && transaction.transactionReceipt && [transaction.transactionReceipt length] > 0))
{
// Transaction is not valid.
return NO;
}
// Pull the purchase-info out of the transaction receipt, decode it, and save it for later so
// it can be cross checked with the verifyReceipt.
NSDictionary *receiptDict = [self dictionaryFromPlistData:transaction.transactionReceipt];
NSString *transactionPurchaseInfo = [receiptDict objectForKey:#"purchase-info"];
...
receiptDict is generated by this code (also included in VerificationController.m)
- (NSDictionary *)dictionaryFromPlistData:(NSData *)data
{
NSError *error;
NSDictionary *dictionaryParsed = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable
format:nil
error:&error];
if (!dictionaryParsed)
{
if (error)
{
#warning Handle the error here.
}
return nil;
}
return dictionaryParsed;
}
which should return an NSDictionary or nil.
ARC is turned on. This problem seems to only occur with iOS 5.0.1 users. While I did make necessary changes to VerificationController.m, this part has been untouched. I can't seem to replicate the problem on my iPad running iOS 5.1.1, but users have said that it is persistent even after reinstalling the app. If anyone can see something simple that I'm not doing right, I'd appreciate it.
EDIT
Follow up question. What does it mean when
- (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)transaction
transaction.transactionReceipt
only provides an NSString and is it safe to ignore?
looks like to me
propertyListWithData:data options:NSPropertyListImmutableformat:nil error:&error];
return a string not a dictionary but it doesnt seems logic. are you sure the problem come from this?

awakeFromInsert never called

I have an application that uses Core Data. I have two data models in the project and I create the ManagedObjectContext by merging the two models. Here the code where I do that:
- (NSManagedObjectModel *)managedObjectModel {
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL* entityURL = [[NSBundle mainBundle] URLForResource:#"User_data" withExtension:#"momd"];
NSManagedObjectModel* entityModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:entityURL];
NSURL* whoURL = [[NSBundle mainBundle] URLForResource:#"WHO_data" withExtension:#"momd"];
NSManagedObjectModel* whoModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:whoURL];
NSArray* models = [NSArray arrayWithObjects:entityModel, whoModel, nil];
__managedObjectModel = [NSManagedObjectModel modelByMergingModels:models];
return __managedObjectModel;
}
None of the attributes in my entities are optional and my app crashes when I try to save my managedObjectContext. I believe this is because some of the attributes are not being set. I have overridden awakeFromInsert: for the parent entity:
- (void) awakeFromInsert
{
[super awakeFromInsert];
NSString* userCFUUID = [[NSUserDefaults standardUserDefaults]objectForKey:#"device_identifier"];
if ( userCFUUID ) {
[self cfuuid:userCFUUID];
} else {
[NSException raise:NSInvalidArgumentException format:#"Entry: awakeFromInsert: cannot find CFUUID"];
}
[self setCreationDate:[NSDate date]]; // the time since Jan 1st 1970 in seconds
[self setEventDate:[NSDate date]];
}
But awakeFromInsert: is never called. I've set a breakpoint and stepped through from the statement where I create the NSManagedObject:
LengthEntry *length1 = [NSEntityDescription insertNewObjectForEntityForName:#"LengthEntry" inManagedObjectContext:moc];
Additional fact that may or may not be relavent:
After creating the datamodel containing the problem entity, I used the Xcode feature to automatically create the classes. I then realised that since I had not specified to do otherwise in the model, xcode named the classes in the plural sense (because that's what I had called them in the model). So, I ended up with "Entries.h" instead of "Entry.h". I went back and manually changed all the classes and specified in the model the name of the classes.
So, I need to figure out why awakeFromInsert is never called.
awakeFromInsert is called exactly once for each object when it is first created.
What you want is awakeFromFetch in order to have it called every time that it is loaded into memory from the store.
Many times, you want the same or similar code in both places.
Out of desperation, I deleted the datamodel and the NSManagedObject classes. I then recreated the model and the classes.
Now, it works. Something screwy must have happened when I manually changed the names of the classes.

NSPersistentStoreCoordinator Crash

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

Core Data model Is throwing Exception

I am using core data in my app. My app was working fine.. I recently reset my simulator setting and now that app is throwing exception. I read all posts and clean my target also but it is not running ,,then I set breakPoint and found exception in last line of this code
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel_ != nil) {
return managedObjectModel_;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"TouristGuide" withExtension:#"momd"];
managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return managedObjectModel_;
}
This code is in my APPdelegate file.. And Exception is
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an
NSPersistentStoreCoordinator with a nil model'
As the error says, the model seems to be nil, or rather the modelURL. You can see this by adding NSLog(#"%#", modelURL), it will print (null).
Make sure that your model is really called TouristGuide and is in the mainBundle, i.e. gets added when building.

Why can't I get the context from the delegate with this code?

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.