could not locate an NSManagedObjectModel for entity name - iphone

This is the code for toggleAddProject method, the Core Data code is almost the same as found in Apple's CoreDataBooks sample, however when I click the add button the app crashes with entityForName: could not locate an NSManagedObjectModel for entity name 'Project' on the line starting with newProjectController.project
-(IBAction)toggleAddProject
{
NewProjectViewController *newProjectController = [[[NewProjectViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
// Create a new managed object context for the new project -- set its persistent store coordinator to the same as that from the fetched results controller's context.
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
self.addingManagedObjectContext = addingContext;
[addingManagedObjectContext setPersistentStoreCoordinator:[[fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
newProjectController.project = (Project *)[NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:addingContext];
[addingContext release];
UINavigationController *addNewNavigationController = [[UINavigationController alloc] initWithRootViewController:newProjectController];
[self.navigationController presentModalViewController:addNewNavigationController animated:YES];
[addNewNavigationController release];
}
Everything has been synthesized, the Project entity exists. I can't figure out why it crashes. Most people seem to be able to fix this error by inserting the following code either in the method itself, or in viewDidLoad:
if (managedObjectContext == nil)
{
managedObjectContext = [(CoreDataBooksAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
When modified for my app delegate it makes no difference. Thanks for any help.

This error has only a few possible sources:
Typo in the Entity name.
Nil managed object context object.
Failure to add the model containing the entity to the persistent store the context uses.
Failure to add the correct persistent store to the context itself.

I had this problem when I had several different NSManagedObjectContexts. The quick way to debug it was to inspect the different connection bits and make sure my entity was listed before calling the context.
NSLog(#"Context: %#",context);
NSLog(#"PS Coord : %#",context.persistentStoreCoordinator);
NSLog(#"MOM : %#", context.persistentStoreCoordinator.managedObjectModel);
NSLog(#"Entities : %#",[[context.persistentStoreCoordinator.managedObjectModel entities] valueForKey:#"name"]);

Use the debugger and confirm that your model is not nil. That is the most common cause of this error. If it is not nil then look for a typo in the entity name.

The Apple docs give some good information on debugging the error entityForName: could not locate an NSManagedObjectModel for entity name 'Foo'.
Look at this section of the Core Data Programming Guide.

Ok I ran across this issue as well and I solved it thusly. The original code was given as:
Event *event = (Event *)[NSEntityDescription insertNewObjectForEntityForName:#"Event" inManagedObjectContext:managedObjectContext];
While the code is concise it seems like the debugger can't display more detailed information about where the error is since you are both creating and configuring a new instance of the 'Event' entity (or whatever your Entity is named).
Instead I broke out this into three lines and the debugger displayed a lot more information:
Event *event = [[NSManagedObject alloc] init];
NSManagedObjectContext *moc = [self managedObjectContext];
event = [NSEntityDescription insertNewObjectForEntityForName:#"Event" inManagedObjectContext:moc];
I found I had not set the correct Type for one of the attributes and I had a typo in my code, all of which the debugger pointed out.

During my development, I could not find Entities that I added later on.
What worked for me: (Basically a sanity-tip)
Uninstall the App EVERY TIME you change the Data Model!
The Data Model is cached by Core Data between installs, to make sure the integrity stays in tact. Delete the App from the simulator / iPhone to be able to test your changes.
PS: does anyone know how to do that automatically?

TechZen is spot on...in my case it was #4. Walk through the steps in the following link and this should help you add the appropriate CoreData methods into an existing project and get everything set up correctly so you don't run into the error you're having.
Adding Core Data To Existing iPhone Projects

Related

Restkit Core data integration with NSManagedObjectContext

For the last weeks I am learning Restkit (v0.10.0) and core data and the possibilities are endless with these great tools. Problem is I am a bit overwhelmed on how to see the bigger picture here. And because of the very fast paced updating of Restkit most of the tutorials/demo code is out of date and not working properly any more.
I have managed to get my tableview filled with data from my json on a remote server. I also worked out on how to make the remote data leading in combination with caching working now, but I am struggling with the NSManagedObjectContext/NSEntityDescription (Core data) and how it works out with Restkit when using POST commands.
If I understand it correctly the record is created in Core Data (after the comment line // Create a new instance ) and after that that data is used to create a POST request so that the record is posted to the server.
This code is being used to create a new record on the server but when the code is executed (I see a record being created on my server) but my tableview is not updated accordingly, the table view is not updated and therefore the new record is first visible when restarting the app. Manually refreshing the data from the server does not help either.
Hopefully someone can give me some pointers, or maybe a tutorial with Restkit/core data and a POST combined. Thanks!
- (void)createGoalWithName:(NSString *)name andDescription:(NSString *)goalDescription
{
Goal* goal = [Goal object];
goal.identifier = 0;
goal.name = name;
goal.goalDescription = goalDescription;
// Create a new instance of the entity managed by the fetched results controller.
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
[NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[self saveContext];
[[RKObjectManager sharedManager].router routeClass:[Goal class] toResourcePath:#"/api/goals" forMethod:RKRequestMethodPOST];
[[RKObjectManager sharedManager] postObject:goal delegate:self];
[self.tableView reloadData];
}
- (void)saveContext {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSError *error = nil;
if (![context save:&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.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
You have to use blocks when using RestKit+CoreData, and forget the router setup:
NSString *postUrl = #"/someurl/newelement";
[ [RKObjectManager sharedManager] loadObjectsAtResourcePath:postUrl usingBlock:^(RKObjectLoader* loader) {
loader.serializationMIMEType = RKMIMETypeJSON;
loader.delegate = nil;
loader.targetObject = nil;
loader.method= RKRequestMethodPOST; // change to GET, POST, PUT etc
}];
Since you don't include the UI code, it's hard to diagnose this problem fully, but one thing that might be happening since the updates are showing up when you restart the app, is that you're not properly synchronizing changes between the various thread's local managed object contexts. RestKit has its own managed object context since it doesn't run on the main UI thread.
The concept of working with multiple threads in Core Data is covered in this Apple document: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html but the gist of it is that you need to register for the notification NSManagedObjectContextDidSaveNotification and then invoke mergeChangesFromContextDidSaveNotification: on the UI thread's managed object context to safely merge the changes done on the RestKit thread.
Keep in mind that the notification will be posted on the RestKit thread, so you probably have to run the update on the main UI thread, e.g. something like this in the method receiving the notification:
[self.managedObjectContextForMainThread performSelectorOnMainThread:#selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES];
Where the property NSManagedObjectContext* managedObjectContextForMainThread has been properly initialized to point to the UI thread's managed object context.
Hope this helps (if you haven't abandoned RestKit altogether...)
I'm still using a slightly older version of Restkit. But one key element is that a primary key attribute must be defined.
So that Restkit can keep your local stored objects and server objects in sync.
In your case, when defining mappings for your Goal object, you would do it like so:
goalMapping.primaryKeyAttribute = #"identifier";

Core Data: Adding objects from NSMutableArray to NSMutableSet?

Judging from the amount of related questions that were brought up, this looks like a frequently asked question which makes me all the more hesitant to ask it. I have looked at a majority of these questions but none of them seem to address the specific problem I am having trouble figuring out.
A little background information on what I'm trying to achieve, how I am going about it, and what issue I am having:
I am trying to parse an XML web service, load that data into an NSMutableArray(Or any other place from which I can access it later), and then take my data and load it into my Core Data model. The first part of this I can do, its once I have my information in the array and trying to load it into Core Data that I cannot seem to progress.
My model(simplified for this question) consists of a route entity that has a one to many relationship with a checkpoint entity. The data I would be trying to load is a variety of attribute information into my route entity, which is not included in my array, and then my list of checkpoints, which is what the array is. My problem is that I cannot reliably add my entire array of checkpoints and then save. For the static case I am using for development, I have a consistent 20 checkpoints being parsed into my NSMutableArray, of these, the most I have been able to transfer into my NSMutableSet aka the checkpoints part of my route entity is 7 before crashing with either a SIGABRT, or EXC_BAD ACCESS, or incorrect selector sent. I have been trying to figure it out for the better part of today with no luck. Now for some code:
NSManagedObjectContext *context = [appDelegate managedObjectContext];
//newRoute is the route that I am trying to create and then store persistently
newRoute = [NSEntityDescription insertNewObjectForEntityForName:#"Route" inManagedObjectContext:context];
//filling in some available attribute information
if (name.text == #"")
[newRoute setValue:[NSDate date] forKey:#"name"];
else
[newRoute setValue:name.text forKey:#"name"];
NSMutableSet *muteSet = [newRoute mutableSetValueForKey:#"myCheckpoints"];
for (int i = 0; i < [appDelegate.checkpoints count]; i++ )
{
Checkpoint *newCheckpoint = [[Checkpoint alloc] init];
[newCheckpoint setName:[[appDelegate.checkpoints objectAtIndex:i] valueForKey:#"name"]];
NSLog(#"Appending %# to set", newCheckpoint.name);
[muteSet addObject:newCheckpoint];
[newCheckpoint release];
}
//myCheckpoints is the route<-->>checkpoints relationship
[newRoute setValue:muteSet forKey:#"myCheckpoints"];
// Save the context.
NSError *error = nil;
if (![context save:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
Out of curiosity, why doesn't the following work?
NSSet *ckPtSet = [[NSSet alloc] initWithArray:appDelegate.checkpoints];
[newRoute setValue:ckPtSet forKey:#"myCheckpoints"];
As far as I understand, and this might be where the problem is... when setting the value of myCheckpoints, the expectation is to be passed an NSSet. When going through with the debugger the initialized set actually contains the 20 objects, but when I try to step past I get the incorrect selector received error again.
Anyways, thank you for taking the time to read my wall of text, if you need more to help please let me know and I will add it asap!
-Karoly
The documentation for [id<NSKeyValueCoding> mutableSetValueForKey:] states that it returns a mutable set proxy that provides read-write access to the unordered to-many relationship specified by a given key. This means that the object returned isn't necessarily an NSMutableSet instance per se, but a proxy wherein any changes you make to that object are reflected in your model's set itself.
This might be why [newRoute setValue:muteSet forKey:#"myCheckpoints"]; is giving you troubles. I find that a better way to think about it is to not have an intermediate object, but to nest calls, e.g.:
[[newRoute mutableSetValueForKey:#"myCheckpoints"] addObject:newCheckpoint];

NSFetchRequest cause SIGABRT OR EXC_BAD_ACCESS

I'm using this simple code for my fetch request
NSArray *fetchResults = [moc executeFetchRequest:request error:&error];
NSLog(#" i want show my result : %#",fetchResults); -> cause SIGABRT
If i'm using on my persistent store just after this creation, i have an error.
PS: the store was save between the populate and the request.
But if i close the app, and reopen ( in this case the store exist), i have no error.
in some case i can view this message : terminate called after throwing an instance of 'NSException'
but i can't access to this exception.
if i count the fetch results, i have a good number, it's really strange.
Thanks for help.
Okay, I have found the problem!
In the populate code, one of my relationships was insert with an autorelease.
Remove this, and now it's OK.
This is not a good solution:
NSManagedObject *relationEntity = [[NSEntityDescription insertNewObjectForEntityForName:#"picture" inManagedObjectContext:moc] autorelease];
Simply remove autorelease:
NSManagedObject *relationEntity = [NSEntityDescription insertNewObjectForEntityForName:#"picture" inManagedObjectContext:moc];
I have forgotten this in core data (don't use release, just set object to nil)!

Update and delete entities in two different process

I'm working on an ipad application that use coredata. It download information on a database that is on the web, and record them in coredata. The application is based on a split view. My problem was to make the update of the data in background. Here is how I've done :
- I've create an NSOperation, that does the download and the update of the data.
- This NSOperation use a different NSManagedObjectContext than the context of the appDelegate, return by this function, that is in the appDelegate :
(NSManagedObjectContext*)newContextToMainStore {
NSPersistentStoreCoordinator *coord = nil;
coord = [self persistentStoreCoordinator];
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc setPersistentStoreCoordinator:coord];
return [moc autorelease];
}
- I've had an observer in the NSOperation, that will call this function in the appDelegate when I save the context, to modify the context of the delegate too :
- (void)mergeChangesFromContextSaveNotification:(NSNotification*)notification {
[[self managedObjectContext]mergeChangesFromContextDidSaveNotification:notification];
}
But I've a problem : when I delete an element in the rootViewController, I really don't know how to manage the changes in the background process, because there is a loop inside that browse all the entities : if I delete one entitie when the background loop is at the same entitie, this is... really bad...
My solution was just to stop the update process when I delete an entitie, and then restart it, simply... But I've realised that the changes made in the "main" context were not apply in the new context I just create for the update.
So I ask you : Why the changes aren't apply in the new context ? If this the wrong way, how do you do this ? Using mergeChangesFromContext or something else ?
Thanks you in advance.
Sorry, my mistakes :
- First, my entities contained other entities, and because of a bad relationship, the entities that was contained in the parent entitie weren't deleted.
- Second, I was thinking that call -cancelAllOperations will stop the current operation, but it's not, you have to check in the nsoperation if the process is cancelled with [self isCancelled].
That's all !
U don't need to take care if somebody will delete something from interface, bcs NSArrayController is thread safe. But if u make updates and delete in same time, u have to take care about it.

iPhone: core data error: +entityForName: could not locate an NSManagedObjectModel for entity name 'Name' [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
insertNewObjectForEntityForName:
See title ^
Code causing this:
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
Name *name = (Name *)[NSEntityDescription insertNewObjectForEntityForName:#"Name" inManagedObjectContext:context];
Feature *feature = (Features *)[NSEntityDescription insertNewObjectForEntityForName:#"thing" inManagedObjectContext:context];
[feature setName:app];
[name addFeaturesObject:feature];
app is an NSString defined earlier.
Things I've tried:
in viewDidLoad:
if (managedObjectContext == nil)
{
managedObjectContext = [(IsidoreAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
Your managed object context is probably not set and the entity "Name" is obviously not valid for a nil context.
In viewDidLoad, you are setting the "managedObjectContext" instance variable for your view controller by using the app delegate which is fine, but then your problem code is using the managed object context from the fetched results controller. Has that been setup yet?
Also, check out this answer to Core Data and UITabBar Controller - help?!
I've ran into the same issue. I created a separate project in xCode4, using "Navigation Based Application" and "Use Core Data" options. Then I copied over the table view with persistent data over to my other application. This is when I ran into the issue. I've defined the Entity along with all the fields, and then had the +entityForName: could not locate an NSManagedObjectModel for entity name 'Name' error
Good thing is it is rather easy to fix:
If you are working along the same path as I did, add this line to your App delegate at the point where you instantiate the controller:
yourViewController.managedObjectContext = self.managedObjectContext;