I am trying to get the values I have saved in one of my core data objects, however I keep getting this error
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Man''
The resulted error is occurring from the code I have written that tries to access the core data object then logg its content, as show shown below.
if ([manufDBVNumber isEqualToNumber:currentDBVersion]) {
// READ FROM CORE DATA
// WRITE TO CORE DATA
NSManagedObjectContext *context = [self managedObjectContext];
NSLog(#"%#", context);
// Test listing all FailedBankInfos from the store
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Man" inManagedObjectContext:self.managedObjectContext]; // This is where the error is happening.
[fetchRequest setEntity:entity];
NSError *error;
NSMutableArray *manufacturerDictionaryArray = [[NSMutableArray alloc] init];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (Manuf *manuf in fetchedObjects) {
NSLog(#"MANA: %#", man.mana);
NSLog(#"SURGE: %#", man.surge);
NSLog(#"HEALTH: %#", manuf.health);
etc//....
This is how I have synthesized the managedObjectContext and fetchedResultsController
// Core-Data variables used for fetching and managing the object
#synthesize fetchedResultsController = __fetchedResultsController;
#synthesize managedObjectContext = __managedObjectContext;
Any help would be greatly appreciated.
You do this:
NSManagedObjectContext *context = [self managedObjectContext];
But then you access this:
self.managedObjectContext
Assuming your NSLog(#"%#", context); shows a valid NSManagedObjectContext, then I would do this:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Man" inManagedObjectContext:context];
Or, change your original declaration to:
self.managedObjectContext = [self managedObjectContext];
In your viewController.m implementation file, right under this bit of code:
- (void)viewDidLoad
{
add this bit of code:
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
Related
I've an annoying problem with Core Data. My app need to get contacts from iPhone and save it in my database. I'm trying to do that in background thread.
I use above code for that:
[self performSelectorInBackground:#selector(fetchingContact) withObject:nil];
-(void)fetchingContact{
// Some Code
for (int i = 0; i < nPeople; i++)
{
//Some Code
NSManagedObjectContext *context = [APP_DELEGATE managedObjectContext];
ABRecordID recordID = ABRecordGetRecordID(person);
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Contact" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"(contactId = '%d')",recordID]];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
//crash
NSArray *contactObjArray = [context executeFetchRequest:fetchRequest error:&error];
//crash
if (error) {}
Contact *contacts;
if (contactObjArray.count == 0) {
contacts = [NSEntityDescription insertNewObjectForEntityForName:#"Contact" inManagedObjectContext:context];
}else {
contacts = [contactObjArray objectAtIndex:0];
}
//Some Code
}
}
In AppDelegate:
- (NSManagedObjectContext *)managedObjectContext
{
NSLog(#"managedObjectContext");
// Returns ;the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc]initWithConcurrencyType: NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
Here I try to save in my Core Data but it crash with error :
* Terminating app due to uncaught exception 'NSGenericException', reason: '* Collection <__NSCFSet: 0x15fad880> was mutated while being enumerated.'` at this line:
NSArray *contactObjArray = [context executeFetchRequest:fetchRequest error:&error];
I search already online, I found a lot of things but nothing helps me. When I run that, there is no place where Core Data is changed, or Contact entity. That does this error very strange.
If I run it in main thread I get no errors/ no crash, but if the app is quit in that time (while is executed) I lose all content from Contact
Please, any help. Tell me if I need to provide more information.
This error happen when you are modifying core data while you try to get them.
That also could be cause of the loop you're doing, you are inserting a new object in coredata without saving before you do an other retrieve. Try saving your managedobjectcontext :
favorite
I have an annoying problem with Core Data. My app need to get contacts from iPhone and save it in my database. I'am trying to do that in background thread.
I use above code for that:
[self performSelectorInBackground:#selector(fetchingContact) withObject:nil];
-(void)fetchingContact{
// Some Code
for (int i = 0; i < nPeople; i++)
{
//Some Code
NSManagedObjectContext *context = [APP_DELEGATE managedObjectContext];
ABRecordID recordID = ABRecordGetRecordID(person);
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Contact" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"(contactId = '%d')",recordID]];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *contactObjArray = [context executeFetchRequest:fetchRequest error:&error];
if (error) {}
Contact *contacts;
if (contactObjArray.count == 0) {
contacts = [NSEntityDescription insertNewObjectForEntityForName:#"Contact" inManagedObjectContext:context];
[context save:&error];
}else {
contacts = [contactObjArray objectAtIndex:0];
}
//Some Code
}
}
If that doesn't solve your problem, maybe check if your method is called multiple times.
I'm having trouble deleting records from Core Data SQLite file. I want to be able to delete the corresponding record from my file when I delete a row from my table view.
Here is what I am doing after fetching all records into allContacts array
NSManagedObject *contactRecord = [allContacts objectAtIndex:arc4random() % allContacts.count];
self.managedObjectID = [contactRecord objectID];
Then called my method that prepares my contacts and then display them on the tableview.
When I delete a row from the table, I call this method
-(void)deleteContactFromFile:(contact *)deletedContact
{
NSLog(#"deleted Contact %#",deletedContact.personID);
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = appDelegate.managedObjectContext;
[context deleteObject:[context objectWithID:self.managedObjectID]];
[context save:nil];
}
The funny thing is I get a random record deleted from my core data file, but not the one I selected. I don't know how to deal with ObjectID thing for deleting a specific NSManagedObject.
If my question is not clear enough please tell me to clarify more.
You should be using an NSFetchedResultsController. It will help you to associate every index path of your table view with a specific managed object. You then do not need to fetch all data and filter through them.
For example, if you have the index path and a fetched results controller it is as easy as
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSManagedObjectContext *context = object.managedObjectContext;
[context deleteObject:object];
[context save:nil];
Note that you not need to go to your app delegate to get the managed object context.
Try this:
- (void)deleteContactFromFile:(contact *)deletedContact {
NSManagedObjectContext *context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest new];
[fetchRequest setEntity:[NSEntityDescription entityForName:#"EntityName" inManagedObjectContext:context]];
NSError *error;
NSArray *rootArray = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *object in rootArray) {
if ([context objectWithID:self.managedObjectID]) {
[context deleteObject:object];
}
}
}
I am making an application where you need to log in with a 4 digit password but there can only be one password at a time. I am trying to save it to core data but whenever the user adds a new password it just adds it to the long list. How can I restrict an entity to only have one instance of itself?
Here is my code just in case it will help:
-(BOOL)savePassword:(NSString*)password{
AppDelegate * appDelegate = [[AppDelegate alloc]init];
NSManagedObjectContext * context = [appDelegate managedObjectContext];
AppData * appData = (AppData*)[NSEntityDescription insertNewObjectForEntityForName:#"AppData" inManagedObjectContext:context];
appData.password = password;
NSError *error;
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"AppData" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"There was an error:%#",error);
}
for (AppData * adata in fetchedObjects) {
NSLog(#"Password:%#",adata.password);
}
return YES;
}
Thanks!
The right approach here is to not put this data in Core Data. If you only have one instance, there's no point in using Core Data to solve the problem. There's no benefit to using Core Data for this. Put it somewhere else. Code solutions miss the point, because even if it works, it's a bad design.
You should do like this, first create fetch request and execute a fetch. check if object exist, update data. else if no data exist create an object and save it.
If name of entity which is storing password.
Your code should look like this
AppData * appData;
NSManagedObjectContext * context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"AppData" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if(fetchObjects.count > 0){
appData = [fetchObjects objectAtIndex:0];//assume there will be one object
// and do reset of thing
}
else{
appData = (AppData*)[NSEntityDescription insertNewObjectForEntityForName:#"AppData" inManagedObjectContext:context];
}
appData.password = password;
// save moc here
[context save:nil];
The problem randomly occurs...
Crashing Location (which is a method in NSOperationQueue)
[self.requestOperationQueue addOperationWithBlock: ^{
NSArray *titleList = [[NSMutableArray alloc] init];
NSArray *allBooks = [[CoreDataManager sharedInstance] fetchBooks];
for (Book *book in allBooks)
[titleList addObject:book.title]; // program crashed here!! failed to fault the value of book.title
}];
I use managedObjectContentChild for NSEntityDescription.
However, executeFetchRequest by managedObjectContent, which is the parent of managedObjectContentChild.
Is that the potential problem?
I tried executeFetchRequest by managedObjectContentChild, however, it leads many more different issues.
However, I am binded to use managedObjectContentChild since program is running in multiple threads by create new CoreDataManager instance for individual thread. Program will run into deadlock without using children MOC.
Thanks in advance!
CoreDataManager.m
- (id)init
{
if ((self = [super init]) != nil)
{
delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// Writer (write data to Persistent Store Coordinator)
writerManagedObjectContext = [delegate writerManagedObjectContext];
// Parent (Fetched Result Controller)
managedObjectContext = [delegate managedObjectContext];
// Child (handling Object Context Saving for individual threads)
managedObjectContextChild = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
managedObjectContextChild.parentContext = managedObjectContext;
bookEntity = [NSEntityDescription entityForName:[Book description]
inManagedObjectContext:managedObjectContextChild];
friendEntity = [NSEntityDescription entityForName:[Friend description]
inManagedObjectContext:managedObjectContextChild];
}
return self;
}
- (NSArray *)fetchBooks
{
// Todo: fix the problem of "CoreData: error: NULL _cd_rawData but the object is not being turned into a fault"
NSArray *results = nil;
if (key == nil)
return results;
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:ascending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
[request setSortDescriptors:sortDescriptors];
NSError *error = NULL;
// results = [managedObjectContextChild executeFetchRequest:request error:&error];
results = [managedObjectContext executeFetchRequest:request error:&error];
if (error != NULL)
NSLog(#"Error fetching - %#", error);
return results;
}
I tried to figure out the following discussion, but still have no clue how to do it...
CoreData: error: NULL _cd_rawData but the object is not being turned into a fault
http://www.cocoabuilder.com/archive/cocoa/311615-weird-core-data-crash.html
Here is the problem,
// use this one
results = [managedObjectContextChild executeFetchRequest:request error:&error];
// not this
// results = [managedObjectContext executeFetchRequest:request error:&error];
so I use managedObjectContextChild (child MOC) instead of managedObjectContext (parent MOC) in order to create distinct MOC for each individual threads. As a rules of concurrency of CoreData.
using managedObjectContext (parent MOC) will not cause the error of object not turning to fault and crashes the app every single time, but it's serious issue if the app happened to be using the same MOC (well, there is only one managedObjectContext in this case) at the exactly the same moment even from different threads.
I have a TableViewController using the CoreData database.
I have another UIviewController from which I want to read the TableViewController's database.
What I did was as follow.
//In UIviewController
-(NSArray *)fetchRecordedDatainsqldatabase
{
// construct a fetch request
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrackerList" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
//[fetchRequest setFetchBatchSize:20];
// Create the sort descriptors array.
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"descript" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:descriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// return the result of executing the fetch request
return [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];}
I have a property of
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
But managedObjectContext is always nil, at the line
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrackerList"
inManagedObjectContext:self.managedObjectContext];
So the program is always crash when it reaches to that line.
What could be the problem?
Generally you can use the managedObjectContext provided to you in the stub code in AppDelegate. If thats the case you can use:
AppDelegate *appD = [[UIApplication sharedApplication] delegate];
then instead of the line:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrackerList"
inManagedObjectContext:self.managedObjectContext];
use:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrackerList"
inManagedObjectContext:appD.managedObjectContext];
and you should replace the return statement to this:
return [appD.managedObjectContext executeFetchRequest:fetchRequest error:&error];
If you are creating your own NSManagedObjectContext object, then you should be setting its persistentStoreCoordinator (which in turns need the managed object model and set the persistent store type).
You can see how to do all this in AppDelegate.m , if you have checked 'use core-data' when creating the project.
Anyway in your case, you already are using a managedObjectContext successfully in your first view controller. So you just need to get the same object over in the second view controller.
For your method to work, you just have to add one line at the top of the code block you provided:
self.managedObjectContext = [[[UIApplication sharedApplication] delegate] managedObjectContext];
Managed Object Context needs to be initialized with a Persistent Store Coordinator and which needs a Managed Object Model. XCode used to provide a boiler plate code for all these implementation in AppDelegate.
As an alternative solution you can try using MagicalRecord
You can set up core data by
[MagicalRecord setupCoreDataStackWithStoreNamed:#"Database.sqlite"];
And you can fetch all the trackerlist values in a context by
NSManagedObjectContext *context = [NSManagedObjectContext defaultContext];
[TrackerList findAllSortedBy:#"descript" ascending:YES inContext:context];
Following link would guide you better
How to make programming in Core Data pleasant