How to update fetchedResultsController after persistent storage change
I'm a weekend warrior when it comes to programming, so I probably did something wrong ...
I have a split view controller, main data, nsfetchedResultsController, all that works fine. I now have the option for the user to create a backup file of the persistentStore.sqlite file. When the user is restored from the backup file, the tableview does not reflect any changes. And on top of that, since then no changes can be made by adding / removing a tableview. When I exit the app and reload it, all the data is there from the backup and everything works well.
How can I get the tableview to get new information from the selected result controller? Or how can I force
Here's some scatter of what I've tried so far with no success:
MasterViewController.m
- (void)viewDidLoad
{
context = [[OSCDStackManager sharedManager] managedObjectContext];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadFetchedResults) name:OSFilesUpdatedNotification object:nil];
- (void)reloadFetchedResults:(NSNotification*)note {
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
if (note) {
[self.tableView reloadData];
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
[self.tableView endUpdates];
[self.tableView reloadData];
}
from the manual refresh dropdown on the table ...
-(void) updateTable{
context = [[OSCDStackManager sharedManager] managedObjectContext];
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
//[self.tableView endUpdates];
[self.tableView reloadData];
[self.refreshControl endRefreshing];
}
- (void)viewWillAppear:(BOOL)animated {
[self.tableView reloadData];
}
- (NSFetchedResultsController *)fetchedResultsController
{
context = [[OSCDStackManager sharedManager] managedObjectContext];
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
//[NSFetchedResultsController deleteCacheWithName:@"cache"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
Even if this is an app for my neighbor, I wouldn't tell him to kill and restart the app after a backup ...
The solution turned out to be a combination of both answers below,
- (void)reloadFetchedResults{
self.fetchedResultsController = nil;
[NSFetchedResultsController deleteCacheWithName:@"cache"];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
[self.tableView reloadData];
}
source to share
nil outside FRC
-(void)reloadData
{
NSError *error = nil;
self.fetchedResultsController = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
else
[self.tableView reloadData];
}
** EDIT ** if it's not obvious with the "i" in front you will need it somewhere in your class
-(NSFetchedResultsController *)fetchedResultsController
{
if (!_fetchedResultsController)
{
_fetchedResultsController = [NSFetchedResultsController alloc]initWithFetchRequest:aFetchRequest
managedObjectContext:aManagedObjectContext // the main thread MOC
sectionNameKeyPath:nil cacheName:nil];
// addional FRC setup etc.
}
return _fetchedResultsController;
}
source to share
Have you removed the cache?
You need to first set the cache name to fetchedResultsController
(note the argument cacheName
at the end):
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:query
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:@"CACHE_NAME"];
Then remove the cache on update:
[NSFetchedResultsController deleteCacheWithName:@"CACHE_NAME"];
After that, load the kernel data again by following these steps:
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error loading data %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
[self.tableView reloadData];
source to share