如何在持久存储更改后刷新fetchedResultsController

时间:2022-04-15 21:39:03

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.

我有一个分屏视图控制器,core data, nsfetchedResultsController,所有这些都很有用。我现在有一个选项供用户创建persistentStore的备份文件。sqlite文件。当用户从备份文件中恢复时,表视图不会反映任何更改。最重要的是,从那时起,不能对tableview添加/删除进行任何持久的更改。当我退出应用程序并重新启动它时,所有的数据都在后台,一切都运行良好。

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

如何强制tableview从fetchedresultscontroller获取新信息?或者我如何强迫

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...

从手动刷新到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];
}

3 个解决方案

#1


2  

nil out your FRC

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

#2


4  

Did you delete the cache?

你删除缓存了吗?

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

您需要首先将缓存名设置为fetchedResultsController(请注意末尾的cacheName参数):

_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:

这样做之后,再次从core data加载:

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

#3


0  

If you are replacing the sqlite file you are probably best tearing everything down and starting with a fresh managed object context. This is a similar question to deleting the store.

如果要替换sqlite文件,那么最好将所有内容都分解,并从一个新的托管对象上下文开始。这与删除存储类似。

#1


2  

nil out your FRC

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

#2


4  

Did you delete the cache?

你删除缓存了吗?

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

您需要首先将缓存名设置为fetchedResultsController(请注意末尾的cacheName参数):

_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:

这样做之后,再次从core data加载:

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

#3


0  

If you are replacing the sqlite file you are probably best tearing everything down and starting with a fresh managed object context. This is a similar question to deleting the store.

如果要替换sqlite文件,那么最好将所有内容都分解,并从一个新的托管对象上下文开始。这与删除存储类似。