【问题标题】:how to refresh fetchedResultsController after persistent store change持久存储更改后如何刷新 fetchedResultsController
【发布时间】:2014-10-21 04:13:36
【问题描述】:

在编程方面我是一个周末战士,所以我可能做错了什么......

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

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

以下是我迄今为止尝试过的一些零散的尝试:

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

【问题讨论】:

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


    【解决方案1】:

    你删除缓存了吗?

    您需要先将缓存名称设置为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];
    

    【讨论】:

      【解决方案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;
      }
      

      【讨论】:

      • 这个终于解决了,但我还需要删除缓存。
      • 您必须将nil 出您的NSFetchedResultsController 吗?我从来没有这样做过。我只需要删除缓存。
      • 这个例子也是错误的,你设置self.fetchedResultsController = nil但是你在下一行使用它。
      • @Evils 我认为说这是错误的不公平......问题是'如何在持久存储更改后刷新 fetchedResultsController' 清除缓存也可以。但你可以拥有sectionNameKeyPath:nil cacheName:nil]' 惰性对象相当普遍......它应该是 Obj C 和 Swift 的第二天性
      • 这是一个了不起的提示!我不知道你必须取消它。没有“无效”电话或类似电话。谢谢,@Magoo!
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-26
        • 1970-01-01
        • 1970-01-01
        • 2011-11-06
        相关资源
        最近更新 更多