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
Related
I am saving various entities into core data. Each time I need to access this data I am reading from Core data and assigning the required entity to a mutable array.
if (managedObjectContext == nil)
{
managedObjectContext = [(iForgetAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Event" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil)
{
// Handle the error.
NSLog(#"mutableFetchResults == nil");
}
[self setEventsArray:mutableFetchResults];
[eventsTableView reloadData];
The problem is, I am retrieving this data from many different pages in the app.
What is the best practice when using Core Data? Should I just load the data in the App Delegate and assign the arrays there?
All advice is greatly appreciated.
Your setup with mutable arrays is already bad practice. Core data can sort, filter and display, arguably much better than mutable arrays.
You should consider using a NSFetchedResultsController to display your data. You can do the filtering and sorting by using predicates and sort descriptors. Such a solution should be infinitely more robust and scalable.
As for your specific question about saving, you can use the managed object context (keep a reference in your class or get it from the app delegate) to save that data anywhere.
Using NSFetchedResultsController gives you the functionality you want. Make sure to also use the NSFetchedResultsControllerDelegate protocol. Use NSFetchRequest to do the retrieval with sorting etc.
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;
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.
I need to use coredata in my View based Application. I created core data file. But I can't access to core data through my Viewbased application without using UITableview.
I used just UITextField and buttons only. I want to need insert records, deletion, updation and search all operations in my application.
Does anyone have some sample code without using navigation based with UITableview?
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = // Your context pointer here
[fetchRequest setEntity:[NSEntityDescription entityForName:#"ObjectName" inManagedObjectContext:context]];
NSError *error;
NSArray *objects = [context executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
for (int index=0; index<[objects count]; index++) {
ObjectName *dmg = (ObjectName *)[menus objectAtIndex:index];
}
This will get you your objects out of the Core Data. You can manipulate this as you see fit as long as you commit it it will be saved in your database. It sounds like you should also search Stack Overflow (and maybe also a search engine) for information about Predicates, which allow you to filter your object graph.
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]);
}
}