Coredata - "NSObjectInaccessibleException - CoreData could not fulfill a fault" - iphone

I am new to Core data and still figuring out the nuts and bolts and this error has been bugging me for hours and I cant seem to find a solution. Any help is greatly appreciated.
The problem is like this
I have two views which fetch data from the server and Update the UI. I have set up the flow this way
view1 -> Send HTTP Req from Server - Receive Callback -> Save Data To Coredata -> Read From Core Data and display on the UI (callback and saving/reading Coredata happen in ViewController)
view2 -> Send HTTP Req from Server - Receive Callback -> Save Data To Coredata -> Read From Core Data and display on the UI (callback and saving/reading Coredata happen in ViewController)
View 2 repeats this process every 3 seconds as this is a auto refresh screen.
The problem is whenever I try to switch between views 1 and 2 real fast, it crashes the app with above error. If I wait for a few seconds on each view (wait for data to be fetched from the server), it works fine. Am I doing something wrong, what do I need to modify?
- (void) refreshData {
[super refreshData];
[[UserDataFactory sharedSingleton] refreshLoggedInUserDataAndRespondTo:self user:self.user];
}
- (BOOL) refreshDataCallback:(QExtendedHTTPOperation*)responseOperation {
[self saveToCoreData: responseOperation.responseArray];
NSMutableArray *tmp = [[NSMutableArray alloc] initWithArray:[self readFromCoreData]];
[self setData: tmp];
[tmp release];
[self.tableView reloadData];
return YES;
}
- (void) saveToCoreData:(NSArray *) responseArray{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"CoreView1" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSError *error;
NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
for (NSManagedObject *managedObject in items) {
[self.managedObjectContext deleteObject:managedObject];
}
for (int i=0; i<[responseArray count]; i++) {
CoreView1 *coreView1_ = [NSEntityDescription insertNewObjectForEntityForName:#"CoreView1" inManagedObjectContext:self.managedObjectContext];
coreView_.id = [[responseArray objectAtIndex:i] id];
[self.managedObjectContext insertObject:coreView1_];
}
[self saveContext:self.managedObjectContext];
}
- (NSArray *) readFromCoreData{
NSEntityDescription *entity = [NSEntityDescription entityForName:#"CoreView1" inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSError *error;
NSMutableArray *fetchedObjects = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
[fetchRequest release];
return [fetchedObjects autorelease];
}
This is the sample code I'm using, even View2 has the same callbacks and follows the same flow.
Edit 1
Forgot to mention this earlier, I always get the error in saveToCoreData method. Also, one more thing to note is that If I remove the code to delete objects it all works fine (I need to remove all the existing data from the table before I save the updated data). Not sure whats happening though.

The reason removing your delete code makes it work is because you are removing the data in the persistent store without updating the other view that still has managed object instances tied to that data still in memory. Remember, while Core Data deals with objects, each object has to have a row in the database behind it. When you delete that row, Core Data gets angry.
So, to fix this problem, and still delete your data, you should have your views listen for NSManagedObjectContextWillSaveNotification and/or NSManagedObjectContextDidSaveNotification notifications and update your views with the most up to date versions of data in your store. It is at this point you should throw away any Core Data objects your views are holding onto, and reload them from the store.

I just resolved this error in my code. Seems my cache was corrupted in some way. I used Christopher Pickslay & Keil Gillard's suggestion of deleting or renaming my cache, and voila, crash resolved.
NSFetchedResultsController index beyond bounds

For info, yesterday, I had the same error. I checked in a live version of the app, and it was still there. yikes.
I ran through all the permutations of adding info to the core data stack until the crash occurred.
I then looked at the sqlite file from the app in the simulator library using SqliteManager. I found a data error in one table. This had occurred as there is a starter db used the first time the app was run. The error was in the starter db.
Ran the app again, testing each field in each table. Found several more occurrences. I remember reading this question, and thought maybe someone else could benefit from my mistake.

Your over releasing fetchedObjects in your readFromCoreData method. executeFetchRequest will return to you autoreleased objects anyway. When the current run loop finished executing (when you're jumping from views) then it attempt to release the objects twice (assuming you haven't used your own autorelease pools).
I'd change
return [fetchedObjects autorelease];
to
return fetchedObjects;

Related

CoreData Application Freezes while performing a fetch Request pthread_mutex_lock

I am using Core Data for managing data base into my app.
I can not post the code here, because its too lengthy. But I guess that I can explain my problem in small line of code along with some snap shots.
+(NSArray *)checkusernameandpassword:(NSString *)entityname username:(NSString *)username password:(NSString *)password
{
managedobjectcontext=[Singleton sharedmysingleton].managedobjectcontext;
NSEntityDescription *entity=[NSEntityDescription entityForName:entityname inManagedObjectContext:managedobjectcontext];
NSFetchRequest *request=[[NSFetchRequest alloc] init];
[request setEntity:entity];
NSPredicate *predicates=[NSPredicate predicateWithFormat:[NSString stringWithFormat:#"userName==\"%#\" AND password==\"%#\"",username,password]];
[request setPredicate:predicates];
//On Below line, My app frezes and goes into deadlock, this happens randomly while performing
//some data request using Core data
NSArray *arrayofrecord=[managedobjectcontext executeFetchRequest:request error:nil];
return arrayofrecord;
}
I am trying to attach some screen shots of the stack of calls (These I see when I pause my app)
The method with a checkmark in the image,at which deadlock occur is mentioned above
You have to lock the thread. This problem appears when multiple threads access the same piece of code. But be were not to end up in to a dead lock.
static NSString *fetchRequest = #"fetchRequest";
NSArray *results;
#synchronized (fetchRequest){
managedobjectcontext=[Singleton sharedmysingleton].managedobjectcontext;
NSEntityDescription *entity=[NSEntityDescription entityForName:entityname inManagedObjectContext:managedobjectcontext];
NSFetchRequest *request=[[NSFetchRequest alloc] init];
[request setEntity:entity];
NSPredicate *predicates=[NSPredicate predicateWithFormat:[NSString stringWithFormat:#"userName==\"%#\" AND password==\"%#\"",username,password]];
[request setPredicate:predicates];
//On Below line, My app frezes and goes into deadlock, this happens randomly while performing
//some data request using Core data
results = [managedobjectcontext executeFetchRequest:request error:nil];
}
return results;
As far as I can understand from your dump, you are calling CoreData Context within a different thread other than MainThread.
Keep in mind that CoreData Context are not thread safe and is your responsability to correct use it.
Apple documentation about CoreData and Thread is very exhaustive.
The solutions proposed above are not safe at all: synchronized statement is useless if you are programming in a concurrent environment (ie. you have more than one thread that we assume can access concurrently the same MOC).
You can try to "confine" your context within the thread life-cycle. For example:
dispatch_async(dispatch_get_global_queue(0, 0), ^(){
NSManagedObjectContext* context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = self.mainContext.persistentStoreCoordinator;
//Make the fetch and export results to main thread
...
});
You can try [private performBlock:^{}]; when using Core Data in multi-thread environment.
For more details, please check this document https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/Concurrency.html#//apple_ref/doc/uid/TP40001075-CH24-SW1

Xcode loading core data lag

I have 3 entities saved in core data. I am loading these in several view controllers in the app - sometimes loading data from all 3. Below is how I am loading this data and assign it to an array. Once it is in the array, then I sort, filter, count or whatever I need to do depending on the current page of the app.
if (managedObjectContext == nil)
{
managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Event" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
[request setReturnsObjectsAsFaults:NO];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil)
{
// Handle the error.
NSLog(#"mutableFetchResults == nil");
}
[self setEventsArray:mutableFetchResults];
The problems I am having are:
I don't like to have lots of duplicate code - and this is appearing on every view controller where core data is needed.
From one entity, I am saving binary data of images which is causing a lag when I load that data
So, is there a way to load from core data using conditions such as eventId = [NSString stringWithFormat:#"%#", currentEventId]
OR (and probably more suitable) have a separate class that loads the data when the app starts. And then I can access the classes arrays (of the loaded data) to use for the current page. And then just reload the data if I save, edit or delete an object.
Any help is much appreciated.
Fro your first question, you should look at MagicalRecord which brings Ruby on Rails' Active Record to CoreData. it will shorten clear your core data code.
Pay attention that if your images are not small you should store them on a separate entity with a relationship to your main entity. this should help you with the lag problem since you will load the image trough the relationship only when you will explicitly ask it to. You can see here the answer of Marcus Zarra (wrote a great book on core data). There is always an option that your images are too big for core data.
Hope it helps

iPhone - App crashes when trying to save new objects after deleting objects in CoreData

Okay, I'm having a problem saving after I've deleted all the objects I have stored in CoreData. I have no problem with saving if I don't delete anything, but as soon as I ask it to delete all the objects (everything deletes with no errors or problems), and then try saving again, it crashes and just gives me a program received signal: SIGABRT. Here's my code.
- (void)deleteStoredData
{
// Define our table/entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:MOVIE_LIST inManagedObjectContext:managedObjectContext];
// Setup the fetch request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
// Fetch the records and handle an error
NSError *error;
NSUInteger count = [managedObjectContext countForFetchRequest:request error:&error];
if (count) {
for (int i = 0; i < count - 1; i++) {
NSManagedObject *eventToDelete = [self.listOfMovies objectAtIndex:i];
[managedObjectContext deleteObject:eventToDelete];
}
}
[request release];
}
I thought it might be me comparing self.listOfMovies to the objects stored, so I did a fresh fetch, copied it to a temp NSMutableArray, then replaced self.listOfMovies with temp. But no changes, still crashes. Did I some how delete the entire record and it no longer exists?
What I want to do is load everything onto the app, then delete all the objects in CoreData, so that when the app closes (or terminates) it saves all the new data in the records. Am I doing this correctly, or is there a much easier way to do this? Oh yea, and I only have one entity that holds 5 NSStrings, so nothing to complicated.
Thanks in advance everyone.
Possibly, when you call the save method, there might be some mixup with some variable such as the managedObjectContext.
Did you try saving right after the deletion (i.e. in your deleteStoredData method above)?
BTW, I would also go with Christopher's code;-).
Deleting managed objects with a for loop like that is error prone and probably corrupting your managedObjectContext. Try the following:
NSFetchRequest * fetch = [[[NSFetchRequest alloc] init] autorelease];
[fetch setEntity:[NSEntityDescription entityForName:MOVIE_LIST inManagedObjectContext:context]];
NSArray * result = [context executeFetchRequest:fetch error:nil];
for (NSManagedObject * event in result) {
[context deleteObject:event];
}
Since you are already have all of managedObject in your array, you do NOT need to do another fetch, just delete them with the code below should be OK.
for (NSUInteger i = 0; i < [self.listOfMovies count] - 1; i++) {
NSManagedObject *eventToDelete = [self.listOfMovies objectAtIndex:i];
[managedObjectContext deleteObject:eventToDelete];
}
If it still have problem, would you please tell me how many managedObjectContext do you have in your App? Are you deleting or saving it in a background thread?
In addition, would you please also post the crash log and the information by type "bt -> enter key" in console after your App crashed?

CoreData DetailTableView BAD_ACCESS Error

Maybe I'm not going about showing a detail for a selected row using CoreData, but I can't figure out why I'm getting a "BAD_ACCESS" error. I've googled around and can't find what I'm looking for.
Basically I use CoreData to populate the data for a Table View. It retrieves all of the title attributes for all of the entities. When the user clicks on a row, I have a Detail View that needs to show the description for that entity. I think I need to make a new NSManagedObjectContext and a new NSEntityDescription for a new NSFetchRequest in my DetailViewController and then use a NSPredicate to say "where title = [user selected title]". I get an error when I select a row. See code:
- (void)viewDidLoad
{
// Do any additional setup after loading the view from its nib.
// Get the objects from Core Data database
Caregiver_Activity_GuideAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:#"Definition"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(title = %#)", self.title];
[request setPredicate:pred];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil) {
NSLog(#"There was an error!");
// Do whatever error handling is appropriate
}
for (NSManagedObject *oneObject in objects) {
[definitionDescriptionTextView setText:[oneObject valueForKey:#"desc"]];
}
[objects release];
[request release];
[super viewDidLoad];
}
I comment out that code and everything works. But when I try to debug with breakpoints, nothing catches. So I'm more confused.
I know CoreData is probably overkill for what I'm doing but this is a learning app for me.
EDIT: I didn't include that I'm using a sqlite database that is pre-populated with the entities.
You can also download my project on my github page.
Normally, with a Core Data backed Master-Detail interface, you don't fetch for the Detail view.
When you select a row in the Master tableview, you are selecting a particular managed object instance. You then pass that managed object instance to the detail view. There is no need to refetch the object that you selected in the tableview.
A good example of this would be the Contacts app. The Master tableview would be a list of Contact objects (displaying the name.) When you select a row, the Master tableview controller takes the specific Contact object associated with the selected row and then passes it to the Detail view controller which then populates the Detail view using data taking from the properties of the passed Contact object.
So, that entire code block where the error occurs is unnecessary.
However, the immediate error in this code is that you are releasing an object you didn't create. In this line:
NSArray *objects = [context executeFetchRequest:request error:&error];
... you are not creating a NSArray instance with a init, new or create method. Instead, you are merely receiving an autoreleased NSArray instance created and returned by the context NSManagedObjectContext instance. When you release an object you did not create here:
[objects release];
... you cause the crash.
Conversely, you do create a NSFetchRequest here:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
... because you used init so you do have to balance that with:
[request relwase];
BTW, this type of code should not be put in viewDidLoad as the method is only called when the view is read in the first time from the nib file on disk. That is only guaranteed to happen once as the view may remain in memory when the user switches to another view. Instead, put code that needs to run each time the view appears in viewWillAppear.

Core Data error: _Unwind_Resume called from function _PFFaultHandlerLookupRow in image CoreData

I'm getting this weird error from Core Date and I cant understand why.
The code below is executed when I delete a row of a UITableView.
I pass a string and an object to the method below and it fetches the article in a database table that has that string and has a foreign key to that object. Then I delete that object and reload the table.
- (void)deleteFavorite:(NSString *)link inFolder:(Favorites *)f {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *favsDecriptor = [NSEntityDescription entityForName:#"Favorites" inManagedObjectContext:context];
[request setEntity:favsDecriptor];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(belongsTo == %#) AND (link = %#)", f, link];
[request setPredicate:predicate];
NSError *error = nil;
NSMutableArray *fav = [[NSMutableArray alloc] init];
fav = [[context executeFetchRequest:request error:&error] retain];
if (![context save:&error]) {
NSLog(#"Cannot fetch the story from the fetch request.");
}
NSLog([[fav objectAtIndex:0] title]);
error = nil;
[context deleteObject:[fav objectAtIndex:0]];
if (![context save:&error]) {
NSLog(#"Can't delete the fav! %#", error);
}
}
The app instantly crashes and I get this message in the console.
But when I launch the app afterwards, the row has been deleted.
Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
_Unwind_Resume called from function _PFFaultHandlerLookupRow in image CoreData.
Please help!
Thanks in advance to everyone!
This is probably related to a bug within Core Data itself. I had the same error come up (I asked about it here in SO) and my only fix was to change the keywords in the predicate that still allowed the same results. It took some experimenting to find the right combination. Not ideal, but that's the best answer I can offer based on my experience.
Is it possible that you are holding a reference to the delete object or that the deleted object is an observer and is getting a callback after its been deleted? I had something similar to this recently, though slightly different error message. In my case, I also crashed upon deletion (under some conditions) but when I relaunched the object-to-be-deleted had, in fact, been deleted.
If you haven't already done so, under the Run menu select Stop on Objective-C Exceptions. This helped me track down the root cause of my crash. In my case it was KVO observer getting callback of change of value of a property of deleted NSManagedObject.