I have 2 viewcontrollers (say A & B) ... I have some records in A now I want to edit the data in the core data.... For that I push the navigation controller to B.. There I edit the data in core data.. Itz working fine.. This the code I use for editing..
NSManagedObjectContext *managedContext = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"CamImage" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
// Set the predicate -- much like a WHERE statement in a SQL database
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", xapp.patientName];
[request setPredicate:predicate];
// Set the sorting -- mandatory, even if you're fetching a single record/object
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
sortDescriptors = nil;
NSError *error;
// Request the data -- NOTE, this assumes only one match, that
// yourIdentifyingQualifier is unique. It just grabs the first object in the array.
CamImage *event = [[managedObjectContext executeFetchRequest:request error:&error] objectAtIndex:0];
[event setMedicineImage:butImage];
[event setMedicineName:text.text];
[event setQuantity:[jst objectAtIndex:0]];
[event setUnit:[jst objectAtIndex:1]];
[event setMeal:meal];
request = nil;
NSMutableArray *mutableFetchResults = [[self.managedObjectContext executeFetchRequest:request1
error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
}
// Set self's events array to the mutable array, then clean up.
[self setCamImage:mutableFetchResults];
NSLog(#"AddMedicineArray:%#",camImage);
[self.navigationController popViewControllerAnimated:YES];
}
In above code I edited the data and fetched it once again..I can found the data got edited properly.. After editing I pop to B.. In the viewwillappear method I once again fetch the data.. But I find the old records only... Once I run the app again I found the edited data got fetched properly.. Here is the code in viewwillappear
-(void)viewWillAppear:(BOOL)animated{
camImage=Nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"CamImage" inManagedObjectContext:self.managedObjectContext];
[request setReturnsObjectsAsFaults:NO];
[request setEntity:entity];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
}
// Set self's events array to the mutable array, then clean up.
[self setCamImage:mutableFetchResults];
viewWillAppear is not being called, because the parent view remains in the view hierarchy the whole time. Instead, implement navigationController:willShowViewController:animated: See this question: iOS 5 viewWillAppear not being called when popping a NavigationController
Related
After [managedObjectContext deleteObject:device]; still showing data in device object.can't delete the data from database.how can i delete the data
if (managedObjectContext == nil)
{
managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", managedObjectContext);
}
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Reserve" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// NSSortDescriptor tells defines how to sort the fetched results
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"number" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSLog(#"sort count%d",[sortDescriptors count]);
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(number = %d)", [sender tag]];
// [fetchRequest setPredicate:predicate];
[fetchedResultsController.fetchRequest setPredicate:predicate];
self.fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSLog(#"Count of array::::%d",[fetchedObjects count]);
NSManagedObject *device = [fetchedObjects lastObject];
NSLog(#"device::::%#",device);
[managedObjectContext deleteObject:device];
NSLog(#"device::::%#",[fetchedObjects lastObject]);
thanks in advance
Deleting the object (device) from the context will not cause it to automatically disappear off the end of the previous result-set (fetchedObjects). The array that you fetch will contain whatever objects existed at the time it was fetched. It does not update itself automatically.
Have you tried running your fetch request again after deleting the object from the context and then checking to see if the device still appears in the result-set? Also, if you really want the object to stay deleted, it's a good idea to save your context as well.
If you want, you can add a delegate to the NSFetchedResultsController, which will call back into your code whenever the result-set changes. You can then use the notification as a cue to reload the array.
I have the following code that fetches a Session object for a particular Exercise object.
This fetch loads data into my UITableView.
The count is fine, I just need a way to extract the Session.timeStamp property so I can set it to UITableViewCell's textLabel property.
Does anyone know how?
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"name == %#", exercise.name]];
NSEntityDescription *sessionEntity = [NSEntityDescription entityForName:#"Exercise" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:sessionEntity];
NSError *error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSMutableArray *mutableSessionArray = [NSMutableArray array];
for (Exercise *ex in results) {
Session *session = [ex exercises];
[mutableSessionArray addObject:session];
}
self.sessionArray = [NSArray arrayWithArray:mutableSessionArray];
Call timestamp property of your mananged object subclass or call valueForKey.
I've got a basic photo album application, on the first view a list of albums is displayed with a subtitle showing how many images are in each album. I've got everything working to add albums, and add images to albums.
The problem is that the image count lines are accurate whenever the app loads, but I can't get them to update during execution.
The following viewdidload correctly populates all lines of the tableview when the app loads:
- (void)viewDidLoad {
[super viewDidLoad];
// Set the title.
self.title = #"Photo albums";
// Configure the add and edit buttons.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addAlbum)];
addButton.enabled = YES;
self.navigationItem.rightBarButtonItem = addButton;
/*
Fetch existing albums.
Create a fetch request; find the Album entity and assign it to the request; add a sort descriptor; then execute the fetch.
*/
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Album" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// Order the albums by name.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"albumName" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
// Execute the fetch -- create a mutable copy of the result.
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
}
LocationsAppDelegate *mainDelegate = (LocationsAppDelegate *)[[UIApplication sharedApplication] delegate];
// Set master albums array to the mutable array, then clean up.
[mainDelegate setAlbumsArray:mutableFetchResults];
[mutableFetchResults release];
[request release];
}
But when I run similar code inside viewdidappear, nothing happens:
{
/*
Fetch existing albums.
Create a fetch request; find the Album entity and assign it to the request; add a sort descriptor; then execute the fetch.
*/
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Album" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// Order the albums by creation date, most recent first.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"albumName" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
// Execute the fetch -- create a mutable copy of the result.
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
}
LocationsAppDelegate *mainDelegate = (LocationsAppDelegate *)[[UIApplication sharedApplication] delegate];
// Set master albums array to the mutable array, then clean up.
[mainDelegate setAlbumsArray:mutableFetchResults];
[self.tableView reloadData];
[mutableFetchResults release];
[request release];
}
Apologies if I've missed the answer to this question elsewhere, but what am I missing?
To troubleshoot, put NSLog statements in a few places in -viewDidAppear:. You would use these log statements to make sure that this method is both being called properly and to examine the contents of mutableFetchResults, at least.
I am trying to add an A-Z index for a core-data populated table using the example here: http://blog.sallarp.com/iphone-core-data-uitableview-drill-down/
However, I can't work out where I can set my sectionNameKeyPath property in the core data helper header file:
Do I need to make a NSFetchedResultsController like they do in CoreDataBooks? Or can I just add it in somewhere here?! Sorry for the ignorance, any thoughts / help would be much appreciated (this is day 3 of tearing my hair out over it).
+(NSMutableArray *) searchObjectsInContext: (NSString*) entityName : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending : (NSManagedObjectContext *) managedObjectContext
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// If a predicate was passed, pass it to the query
if(predicate != nil)
{
[request setPredicate:predicate];
}
// If a sort key was passed, use it for sorting.
if(sortKey != nil)
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
}
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
[request release];
return mutableFetchResults;
}
You need to implement the appropriate table view datasource methods (sectionIndexTitlesForTableView: and tableView:sectionForSectionIndexTitle:atIndex:).
I would recommend using an NSFetchedResultsController to do this. Check out this answer to Core Data backed UITableView with indexing for example code.
I am placing an NSFetchedResultsController into my code so I get that nice automatic sectioning of my table view data.
So I am running a test to make sure everything works properly. I have a single Book entity in my persistent store. I will first perform the fetch the old way, then I will try to use NSFetchedResultsController. The difference between the 2 blocks of code is just 2 lines.
Code without NSFetchedResultsController:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kBookEntityName inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"title" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
//The following 2 lines will be replaced by the NSFetchedResultsController
NSMutableArray *mutableFetchResults = [[[self.managedObjectContext executeFetchRequest:request error:nil] mutableCopy] autorelease];
Book *result = (Book*)[mutableFetchResults objectAtIndex:0];
NSString* title = [result valueForKey:#"title"];
NSString* priority = [result valueForKeyPath:#"priority.name"];
[request release];
Now I substitute in the lines for the NSFetchedResultsController:
NSFetchedResultsController* fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"title" cacheName:#"BookList"];
Book *result = (Book*)[fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
Seems pretty cut and dry. The first code block properly fetches the single Book entity. The code with the NSFetchedResultsController, however, does not. Instead it returns nil.
My question is: Am I properly configuring the NSFetchedResultsController in this example?
(note, the fetchedObjects property of the NSFetchedResultsController is also nil)
I think you still need to tell the NSFetchedResultsController to actually perform the fetch:
NSError *error;
BOOL success = [controller performFetch:&error];
(taken from the example in the NSFetchedResultsController reference)
one other thing that seems odd: do you really want to use "title" as the sectionNameKeyPath? won't that basically create a separate section for each book?
You need to initialize your NSFetchedResultsController only once, as follows.The code assumes
NSFetchedResultsController *fetchedResultsController;
NSManagedObjectContext *managedObjectContext;
are declared in the header of your controller, and that managedObjectContext is already properly initialized.
- (void)viewDidLoad {
[super viewDidLoad];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Handle error
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
NSLog(#"%d objects fetched", [[fetchedResultsController fetchedObjects] count]);
}
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:kBookEntityName inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
/* Optional settings
[request setResultType:NSManagedObjectResultType];
[request setIncludesPropertyValues:YES];
[request setIncludesPendingChanges:NO];
[request setReturnsObjectsAsFaults:NO];
*/
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"title" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];;
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:#"title" cacheName:#"BookList"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[request release];
return fetchedResultsController;
}