0

我有一个由NSFetchedResultsController驱动的UITableView。我调用了一种方法来创建一个NSPredicate,用于过滤自今天起拥有时间戳的实体。在我的NSFetchedResultsController中,我应用谓词。NSFetchedResultsController刷新UITableView条目没有重新加载口吃

if (appDelegate.displayTodayOnly) { 
    [fetchRequest setPredicate:datePredicate]; 
} 

这一切都很好。但是,偶尔我需要查看“今天”之前的条目。我在桌子视图上向下滑动,当它已经在桌子的开始处时。

-(void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 
    if (self.tableView.contentOffset.y<0) { 
     if (appDelegate.displayTodayOnly) { 
      [appDelegate setDisplayTodayOnly:NO]; 
      NSInteger resultsOffset = [[self.fetchedResultsController fetchedObjects] count]; 
      //[self.tableView beginUpdates]; 
      [__fetchedResultsController release]; 
      __fetchedResultsController=nil; 
      NSError *error; 
      if (![[self fetchedResultsController] performFetch:&error]) { 
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       exit(-1); // Fail 
      } 
      //[self.tableView endUpdates]; 
      NSInteger fullCount = [[self.fetchedResultsController fetchedObjects] count]; 
      if (fullCount>resultsOffset) { 
       NSUInteger sect = [[self.fetchedResultsController sections] count]-2; 
       id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:sect]; 
       NSUInteger rows = [sectionInfo numberOfObjects]-1; 
       NSIndexPath *indexing = [NSIndexPath indexPathForRow:rows inSection:sect]; 
       NSLog(@"IndexPath = section:%d row:%d",sect,rows); 
       [self.tableView reloadData]; 
       [self performSelector:@selector(scrollToIndexPath:) withObject:indexing afterDelay:0.0001]; 
      } 
     } 
    } 
} 

这也适用,但不雅。它放弃fetchedResultsController,并从条目开始的时间开始重新加载表。然后,我将它滚动到上一个表的条目上方的索引路径。

我想要发生的是要在当前表的顶部之前加载和插入条目。有谁知道一个优雅的方式来改变提取的发生?

回答

0

我发布了我的解决方案,希望它可以帮助其他需要帮助的人。

我仍然将NSFetchedResultsController实例设置为零,并获取具有不同谓词的新实例。然后,而不是重新加载表(导致迷失方向的跳转),在for(循环)中,我手动调用[self.tableView insertSections:[NSIndexSet indexSetWithIndex:i] withRowAnimation:UITableViewRowAnimationNone];,该方法几乎直接从<NSFetchedResultsControllerDelegate>方法的样板controllerWillChangeContent:中取出。这是有效的,因为最后一部分总是将成为今天的部分。如果今天没有任何条目,那么我需要重新加载数据,因为插入的部分数量不一致,因为今天的空白部分算作部分。

-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 
{ 
    if (self.tableView.contentOffset.y<0) { 
     if (appDelegate.displayTodayOnly) { 
      [appDelegate setTodayOnlyMemory:NO]; 
      NSUInteger resultsOffset = [[self.fetchedResultsController fetchedObjects] count]; 
      [__fetchedResultsController release]; 
      __fetchedResultsController = nil; 
      self.fetchedResultsController = nil; 

      NSError *error = nil; 
      if (![self.fetchedResultsController performFetch:&error]) 
      { 
       NSLog(@"error in fetched results controller of Memory Notes"); 
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       abort(); 
      } 
      if (resultsOffset) { 
       [self.tableView beginUpdates]; 
       NSInteger afCount = ([[self.fetchedResultsController sections] count]-1); 
       for (NSInteger i=0; i<afCount; i++) { 
        [self.tableView insertSections:[NSIndexSet indexSetWithIndex:i] withRowAnimation:UITableViewRowAnimationNone]; 
       } 
       [self.tableView endUpdates]; 
      } else { 
       [self.tableView reloadData]; 
      }    
      [self performSelector:@selector(scrollToSpot) withObject:nil afterDelay:0.01f]; 
     } 
    } 
} 

此外,这里是我的scrollToSpot方法结束在正确的位置。

-(void)scrollToSpot 
{  
    NSArray *sectArray = [self.fetchedResultsController sections]; 
    if ([sectArray count]>1) { 
     id <NSFetchedResultsSectionInfo> sectionInfo = [sectArray objectAtIndex:([sectArray count]-2)]; 
     NSInteger theRow = [sectionInfo numberOfObjects]-1; 
     NSIndexPath* ipath = [NSIndexPath indexPathForRow:theRow inSection:([sectArray count]-2)]; 
     NSLog(@"Row:%d",ipath.row); 
     [self.tableView scrollToRowAtIndexPath:ipath atScrollPosition:UITableViewScrollPositionTop animated:NO]; 
     NSLog(@"ContentOffset:%.0f",self.tableView.contentOffset.y); 
    } 
} 
1

我最常做的是设置

self.fetchedResultsController = nil; 

并重新加载。它非常高效并且代码最少(假设您像在Xcode模板中一样加载并创建提取的结果控制器)。

+0

是的,它的工作,这是我的scrollViewDidEndDragging方法发生了什么。我试图了解是否可能有一种方法来减轻重新加载,所以结果不会跳来跳去。 – JacobFennell 2012-02-07 16:49:12