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];
}

      

+3


source to share


3 answers


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;
}

      

+2


source


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];

      

+4


source


If you're replacing the sqlite file, you're probably best off breaking everything and starting with a fresh managed object context. This is a similar question for deleting a repository.

0


source







All Articles