core data delete not work - iphone

I use the following code to populate a UITableView
self.navigationItem.leftBarButtonItem = self.editButtonItem;
test_coredataAppDelegate *appDelegate = (test_coredataAppDelegate *)[[UIApplication sharedApplication] delegate];
self._context = appDelegate.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"patients" inManagedObjectContext:_context];
[fetchRequest setEntity:entity];
NSError *error;
self.PatientsList = [_context executeFetchRequest:fetchRequest error:&error];
self.title = #"patients";
[fetchRequest release];
where PatientsList is NSArray
when I want to delete record I use
[self._context deleteObject:[_PatientsList objectAtIndex:indexPath.row]];
NSError *error;
if (![_context save:&error]) {
// Handle error
NSLog(#"Unresolved error series %#, %#", error, [error userInfo]);
}
[PatientsList removeObjectAtIndex:indexPath.row] ;
[self.tableView reloadData];
but this doesn't have any effect.
How can I solve this issue and delete successfully, especially when my model contain relations?

Here you delete it from db but not from array so you need to delete from array or call database for again load the arry with new db details.
so for first approach delete it from array make your array mutable and use
removeObjectAtIndex method for deleting the object
or in second approach you need to fetch data again from core data.
and then reload table by using
[table reloadData];

Could you post a little more information about the results you're getting from fetch requests before and after you call deleteObject:? You could also check the userInfo property of the NSError object that you pass to some Core Data functions as that often gives very help information in Core Data. Also remember that your modifications aren't "set in stone" until the data model is saved using the save: method of your NSManagedObjectContext instance.
The way Core Data handles the relationships of a deleted object is defined in your Core Data schema (.xcdata file), which you can edit in Xcode. You can set the delete action of relationships to "Deny", "Nullify", "Cascade" or "No Action" here. See the 'Relationship Delete Rules' section of the documentation found here.

Related

Populating the Tableview from the Core Data

I have performed the save operation in core data and it is successfully done .It stores the data .I have also fetched the data into the log. This is my code for fetching data in log but I dont know how to fetch this data in TableView.
NSError *error;
DemoAppCoreDataAppDelegate *appdelegate = (DemoAppCoreDataAppDelegate *)[[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName: #"Employee" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedobject = [context executeFetchRequest:fetchRequest error:&error];
tablearray = [[NSMutableArray alloc] initWithArray:fetchedobject copyItems:YES];
for (NSManagedObject *info in fetchedobject ) {
NSLog(# "%#",[info valueForKey:#"name"] );
}
[fetchRequest release];
I would recommend to use a NSFetchedResultsController.
Apple provides complete sample code in the NSFetchedResultsController documentation
The NSFetchedResultsController is specifically designed to work in between a tableView and Core Data. It makes everything a lot easier.
For example it will automatically insert and delete rows when you add or remove objects from the core data. For this you have to implement the NSFetchedResultsControllerDelegate protocol. The full sample code for this is in the protocol documentation
Use fetchedobject as dataSource to the tableView.
After [fetchRequest release]; , set the delegate and datasource for the tableView programatically.
The best way in this case is to inspect some working example I think. Look at the apple's example project Recipies, good one btw: easy and gives a good picture of how the things with CoreData and tableViews should be done:
http://developer.apple.com/library/ios/#samplecode/iPhoneCoreDataRecipes/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008913

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

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;

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.

Query interface for iPhone CoreData store

another iPhone newbie question...
I have the following:
NSPersistentStoreCoordinator
NSManagedObjectContext
NSManagedObjectModel
Is it possible to run queries directly on the store (since its a sqlite DB)? I'm trying to delete all the records from a tableview, and figured a "DELETE FROM table" would be nice and quick as opposed to looping through the records and removing them manually (which i'm also struggling with).
Thanks for your time,
James
Core data acts as a wrapper for the underlying data store, so it's not really a great idea to begin circumventing core data. Additionally, core data adds additional information to your DB, so directly accessing the DB may (or may in the future) cause problems.
To delete all records via core data, I have the following:
+ (void) deleteAll {
NSManagedObjectContext *managedObjectContext = [(myAppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:[[self class] description] inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
for (NSManagedObject *managedObject in items) {
[managedObjectContext deleteObject:managedObject];
NSLog(#"%# object deleted",[[self class] description]);
}
}

The entity xxx is not key value coding-compliant for the key "(null)"

I am trying to write a simple table view editor for a Core Data entity. Unfortunately I'm running into problems.
The error occurs when adding the very first entity to the table. The process for bringing up the modal dialog is as follows:
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Group" inManagedObjectContext:context];
insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
NSManagedObject *newManagedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
NameEditController *dialog = [[NameEditController alloc] init];
dialog.managedObject = newManagedObject;
[newManagedObject release];
UINavigationController *navCtrlr = [[UINavigationController alloc] initWithRootViewController:dialog];
navCtrlr.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[[self navigationController] presentModalViewController: navCtrlr animated:YES];
[navCtrlr release];
Inside of NameEditController, I have this after the Done button is pressed:
NSString* name = self.nameLabel.text;
[self.managedObject setValue:name forKey:#"name"];
NSError *error = nil;
if (![managedObject.managedObjectContext save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
UIViewController *ctrl = [self parentViewController];
[ctrl dismissModalViewControllerAnimated:YES];
The very first time I create an object (when the list is empty) I get this:
Exception was caught during Core Data change processing: [ valueForUndefinedKey:]: the entity Group is not key value coding-compliant for the key "(null)".
If I fill out the 'name' field before bringing up the dialog, I am able to add the first entity successfully:
[newManagedObject setValue:#"New Group" forKey:#"name"]; // this works
I am using NSFetchedResultsController to manage the table view BTW.
Thanks!
In your first code block, the third line of code appears to be out of context. Not sure if there's something there that could be contributing.
Secondly, the easiest way to get yourself an NSManagedObject into a NSManagedObjectContext from an entity name is to use the [NSEntityDescription insertNewObjectForEntityName:inManagedObjectContext:] selector.
So, I'd do something like:
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityName:#"Group" inManagedObjectContext:context];
You won't need to release newObject anymore, since the [NSEntityDescription insertNewObjectForEntityName:inManagedObjectContext:] selector will return an object with a retain count of 0. Also, make sure that you have NameEditController specifying its managedObject property as retained.
To address your actual issue, it sounds like maybe you have 'name' specified as a required property in your data model? A screenshot showing the details for 'name' in your data model would help.
Yarr... sorry guys, it was actually in my didChangeObject:atIndexPath:forChangeType:newIndexPath: function hastily copied from elsewhere. Apparently an exception thrown here can get obscured inside of the save: method.