1

I have a tableview in a tab bar application.

I am loading the data in viewDidLoad

managedObjectContext = nil;
managedObjectContext = [(RecipesAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"BrilliantMustache" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"badge.length > 0"];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"badge" ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1,sortDescriptor2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"badge" cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor1 release];
[sortDescriptor2 release];
[sortDescriptors release];

I am attempting to reload the data in viewWillAppear

- (void)viewWillAppear:(BOOL)animated {
    [self.tableView reloadData];
}

In this view, I call another view, which when changed, updated the core data when released. When I navigate back to the tableview, it does not update. The only way it will update, is if I quit the app and reload from scratch.

In total there are 2 separate table views. The strange thing is, the first tableview DOES refresh.

Any thoughts? Rob

roberthuttinger
  • 1,172
  • 1
  • 17
  • 31

2 Answers2

2

You need to do what you do in viewDidLoad in viewWillAppear. viewDidLoad is only called at startup, so despite changing the data, your view never changes its own local data, so when you call reloadData it still uses the old data.

Edit:

What you should have:

- (void)viewWillAppear:(BOOL)animated {
    managedObjectContext = nil;
    managedObjectContext = [(RecipesAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"BrilliantMustache" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"badge.length > 0"];
    [fetchRequest setPredicate:predicate];
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"badge" ascending:YES];
    NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1,sortDescriptor2, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"badge" cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;
    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor1 release];
    [sortDescriptor2 release];
    [sortDescriptors release];

    [self.tableView reloadData];
    [super viewWillAppear:animated];
}

- (void)viewDidLoad:(BOOL)animated {
    [super viewDidLoad:animated];
}
jrtc27
  • 8,496
  • 3
  • 36
  • 68
  • see code above, `- (void)viewWillAppear:(BOOL)animated { [self.tableView reloadData]; }` it is being called in `viewWillAppear` – roberthuttinger Dec 08 '11 at 20:55
  • `reloadData` just tells the table view to refresh the table based on the data **you provide in your table view data source and delegate**. The problem is that although you tell your table view to reload data, the data it is loading from is outdated. – jrtc27 Dec 08 '11 at 21:03
  • ok that makes sense, but given I am loading the data in the view, could you give me an idea as to how to refresh the data, without reloading the data as above? Or do I need to have to reload the data from scratch? thanks! Is there a way to force the entire view to reload? – roberthuttinger Dec 08 '11 at 21:18
  • 1
    Well, instead of having all your Core Data code (the first block of code which you say is in `viewDidLoad`) in `viewDidLoad`, I would put it in `viewWillAppear` followed by your `reloadData`. – jrtc27 Dec 08 '11 at 21:45
  • So that works now, I dont know why it didnt work before, perhaps the missing `[super viewWillAppear:animated];` was the issue :D thanks – roberthuttinger Dec 08 '11 at 23:54
  • It's because viewDidLoad is only called *at app startup*. This means that you then update your core data from another view, but when you return, as viewDidLoad is never called, your view never retrieves this new data, and all calling reloadData does is get your table to request the latest data from your view, but because your new data has not been retrieve by the view, it gives it the old data. – jrtc27 Dec 09 '11 at 07:15
  • 1
    Just remember that -performFetch: can be a potentially expensive operation that you may not want happening every time the view appears since a trip to the disk is required. – Mark Adams Dec 09 '11 at 08:27
  • True - you might just want a boolean declared somewhere to indicate whether your data has been modified. – jrtc27 Dec 09 '11 at 08:42
0

Have you implemented the NSFetchedResultsControllerDelegate methods properly? The FRC should be handling updating the table when it receives a notification of changes from the managed object context...

Edit: NSFetchedResultsController Class Reference

Mark Adams
  • 30,776
  • 11
  • 77
  • 77
  • you mean: `@interface PickerViewController : UIViewController { etc...`? – roberthuttinger Dec 08 '11 at 21:38
  • 1
    That just declares that `PickerViewController` conforms to the NSFetchedResultsControllerDelegate protocol. There are 4 methods to implement for full change tracking. `-controllerWillChangeContent:`, `-controllerDidChangeContent:` etc. I've updated my answer with a link to the class reference. – Mark Adams Dec 08 '11 at 21:40
  • 1
    so if I altered a field in another view and returned to the view I want to update, this would trigger `didChangeObject`? ill take a look at the docs and see what I can use here, thanks! – roberthuttinger Dec 08 '11 at 23:43