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

时间:2014-10-21 04:13:37

标签: ios objective-c uitableview core-data nsfetchedresultscontroller

在编程时我是个周末战士,所以我可能做错了......

我有一个拆分视图控制器,核心数据,nsfetchedResultsController,一切都很好。我现在可以选择让用户创建persistentStore.sqlite文件的备份文件。当用户从备份文件还原时,tableview不会反映任何更改。最重要的是,从tableview添加/删除后不能进行任何持久的更改。当我退出应用程序并重新启动它时,所有数据都来自备份,并且一切正常。

如何强制tableview从获取的结果控制器获取现在的新信息?或者我如何强制

以下是我迄今为止尝试过的一些消息,但没有成功:

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

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

即使这是我的邻居的应用程序,我也讨厌在备份后告诉他杀死并重新启动应用程序......

解决方案最终成为以下两个答案的组合,

- (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 个答案:

答案 0 :(得分:4)

您是否删除了缓存?

您需要先将缓存名称设置为fetchedResultsController(注意最后的cacheName参数):

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

然后在进行更新时删除缓存:

[NSFetchedResultsController deleteCacheWithName:@"CACHE_NAME"];

执行此操作后,再次从核心数据加载:

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

答案 1 :(得分:2)

没有你的FRC

-(void)reloadData
{
    NSError *error = nil;
    self.fetchedResultsController = nil;

    if (![self.fetchedResultsController performFetch:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }
    else
        [self.tableView reloadData];

}

**编辑**以防“自我”和“自我”不明显。在前面,你需要在班上的某个地方

-(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 :(得分:0)

如果要替换sqlite文件,最好将所有内容拆除,并从新的托管对象上下文开始。这是删除商店的类似问题。