Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to refresh fetchedResultsController after persistent store change

I'm a weekend warrior when it comes to programming, so I have probably done something wrong...

I have a split view controller, core data, nsfetchedResultsController, all that works great. I now have an option for the user to create a backup file of the persistentStore.sqlite file. When the user restores from a backup file, the tableview doesn't reflect any change. And on top of that, can't make any lasting changes from then on from the tableview add/delete. When I quit the app and restart it, all the data is there from the back up and all is working well.

How can I force the tableview to get the now new info from the fetched results controller? Or how do I force the

Here's some scatterings of what I have tried so far without 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 a manual refresh pulldown on the tableview...

-(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 though this is an app for my neighbor, I'd hate tell him to kill and restart the app after a back up...

Solution ended up being 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];
}
like image 721
Mark Avatar asked Oct 21 '14 04:10

Mark


2 Answers

Did you delete the cache?

You need to first set the cache name to the fetchedResultsController (notice the cacheName argument at the end):

_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:query
                                                                managedObjectContext:context
                                                                  sectionNameKeyPath:nil
                                                                           cacheName:@"CACHE_NAME"];

Then delete the cache when you make an update:

[NSFetchedResultsController deleteCacheWithName:@"CACHE_NAME"];

After doing this, load from core data again by doing this:

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];
like image 63
KVISH Avatar answered Sep 28 '22 07:09

KVISH


nil out your 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 ** in case it's not obvious with the 'self' at the front you'll need 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;
}
like image 36
Magoo Avatar answered Sep 28 '22 07:09

Magoo