【问题标题】:NSFetchResultsController object refresingNSFetchedResultsController 对象刷新
【发布时间】:2026-02-09 22:30:01
【问题描述】:

我有 2 个视图。一个使用 NSFetchResultsController 显示来自 Core Data 的购物清单。第二个使用简单的 NSFetchRequests 显示此列表中的项目。两个视图都包含 UITableView。

当我启动应用程序时,我会创建 NSFetchResultsController(由 ActiveFetchResults 子类化)

-(id)initActiveFetch{

      NSFetchRequest *request = [[NSFetchRequest alloc] init];

      NSEntityDescription *entity = [NSEntityDescription entityForName:@"Lista" inManagedObjectContext:[CoreDataHandler context]];

      [request setEntity:entity];

      NSPredicate *predicate = [NSPredicate predicateWithFormat:@"archive == 0 AND deleted == NO"];

      [request setPredicate:predicate];

      NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"position" ascending:NO];

      NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

      [request setSortDescriptors:sortDescriptors];

      [sortDescriptors release];

      [sortDescriptor release];

      if (self=[[ActiveFetchResults alloc] 

                    initWithFetchRequest:request 

                    managedObjectContext:[CoreDataHandler context] 

                    sectionNameKeyPath:nil 

                    cacheName:nil]) 

      {

            self.delegate = self;

      }

      [request release];

      return self;

} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return [[self sections] count];

} 

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {

    id <NSFetchedResultsSectionInfo> sectionInfo = [[self sections] objectAtIndex:section];

    return [sectionInfo numberOfObjects];

} 

- (NSInteger)numberOfRowsInSection{

    id <NSFetchedResultsSectionInfo> sectionInfo = [[self sections] objectAtIndex:0];

    return [sectionInfo numberOfObjects];

} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

      ActiveListsCell* cell;

      cell = (ActiveListsCell*)[tableView dequeueReusableCellWithIdentifier:@"ActiveLists"]; 

      if (cell == nil) {

            cell = [[[ActiveListsCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"ActiveLists"] autorelease];

      } 

      NSManagedObject *managedObject = [self objectAtIndexPath:indexPath];

      [cell setLista: (Lista*)managedObject];

      NSLog(@"%@, %@, %d ",managedObject, [managedObject name], [[managedObject items] count]);

      cell.activeListsDelegate = self;

      [cell.roundedView setAlpha:1.0];

      cell.button.alpha = 1.0; 

      cell.counter.alpha = 1.0;

      return cell;

} 

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 

    id <NSFetchedResultsSectionInfo> sectionInfo = [[self sections] objectAtIndex:section];

    return [sectionInfo name];

} 

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {

    return [self sectionIndexTitles];

} 

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {

    return [self sectionForSectionIndexTitle:title atIndex:index];

} 

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {

    [self.tableView beginUpdates];

} 


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo

               atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { 

    switch(type) {

        case NSFetchedResultsChangeInsert:

            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]

                                      withRowAnimation:UITableViewRowAnimationFade];

            break; 

        case NSFetchedResultsChangeDelete:

            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]

                                      withRowAnimation:UITableViewRowAnimationFade];

            break;

    }

} 

//-(BOOL)performFetch:(NSError **)error{

// ActiveFetchResults* ss = self;

// self = [self initActiveFetch];

// 

// self.listView = ss.listView;

// self.listView.activeFetch = self;

// [self.listView.tableView setDelegate:self];

// [self.listView.tableView setDataSource:self];

// 

// [ss release];

// return [super performFetch:error];

//} 

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject

         atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type

        newIndexPath:(NSIndexPath *)newIndexPath { 

    UITableView *tableView = self.tableView; 

    switch(type) { 

        case NSFetchedResultsChangeInsert:

            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]

                                           withRowAnimation:UITableViewRowAnimationFade];

            break; 

        case NSFetchedResultsChangeDelete:

            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]

                                           withRowAnimation:UITableViewRowAnimationFade];

            break; 

        case NSFetchedResultsChangeUpdate:

                  if ([anObject isKindOfClass:[Lista class]]) {

                        Lista* lista = (Lista*)anObject;

                        if ([[lista deleted] boolValue]) {

                              [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]

                                                       withRowAnimation:UITableViewRowAnimationLeft];

                        }

                  }

                  else

                        [self configureCell:[tableView cellForRowAtIndexPath:indexPath]

                                    atIndexPath:indexPath];

            break; 

        case NSFetchedResultsChangeMove:

            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]

                                           withRowAnimation:UITableViewRowAnimationFade];

            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]

                                           withRowAnimation:UITableViewRowAnimationFade];

            break;

    }

} 


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {

    [self.tableView endUpdates];

} 

-(void)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath{

      ActiveListsCell* activeCell = (ActiveListsCell*)cell;

      NSManagedObject *managedObject = [self objectAtIndexPath:indexPath];

      [activeCell setLista: (Lista*)managedObject];

}

当我转到第二个视图并通过将项目对象添加到核心数据来为选定列表添加新项目时,我返回到列表视图它仍然显示旧数量的对象。 list 的 items 属性应该向我显示该列表的所有 Items 对象是一个 NSarray 对象,其项目计数不包括新添加的对象。但是第二个视图也向我显示了所有新添加的项目。

简而言之,使用 NSFetchResultsController 看起来我已经从第一次获取中冻结了所有对象,并且尽管使用了“performFetch:”函数,但没有响应更改。在第二个视图中使用简单的 NSFetchRequest 时一切正常。

谁能告诉我为什么 NSFetchResultsController 对象保持冻结状态并且在核心数据记录更改时不会更改?

【问题讨论】:

    标签: iphone objective-c core-data nsfetchedresultscontroller


    【解决方案1】:

    可能的问题:

    1. 您是否在更新或添加对象后保存了NSManagedObjectContext

    2. 尝试添加此案例

      case NSFetchedResultsChangeUpdate: [self.tableView reloadData]; break;

    在您的 - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id &lt;NSFetchedResultsSectionInfo&gt;)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type 方法中

    1. 每次执行fetch后尝试重新加载tableview的数据:

      [self.tableView reloadData];

    2. 如果还是不行,请查看 Apple 的核心数据配方示例代码:http://developer.apple.com/library/ios/#samplecode/iPhoneCoreDataRecipes/Introduction/Intro.html

    【讨论】: