2011-05-24 43 views
8

每当我打电话调用reloadRowsAtIndexPaths删除的tableView contentOffset

reloadRowsAtIndexPaths 

我的UITableView contentOffset被删除,是否有委托方法我可以用它来捕捉表视图更新和设置偏移再次使之保持在适当位置和不动画到视图中,或者干脆阻止它这样做?

我设置contentOffest在viewDidLoad中:

下面是一个例子用法:

[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[params valueForKey:@"index"], nil] withRowAnimation:UITableViewRowAnimationFade]; 

其去除contentOffset并动画眼帘,这是我不想要的。

更具体地说,当被重载的行位于indexPath.section 0和indexPath.row 0,即顶行时,似乎会发生这种情况。


更多信息

我一个异步请求后调用reloadRowsAtIndexPaths从服务器获取的图像。它基本上就像这样:

  • 的cellForRowAtIndexPath被称为该检查磁盘上的拇指文件的存在,如果该文件不存在的占位符被加载在它的位置和异步请求在后台启动线程来获取图像。
  • 当图像下载完成时,我会拨打reloadRowsAtIndexPaths以获取正确的单元格,以便正确的图像淡入以代替占位符图像。
  • 细胞的量可以是不同的,因为该请求被称为内部的cellForRowAtIndexPath使得图像在加载作为细胞负载

的cellForRowAtIndexPath文件检查

paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_small.gif",[[listItems objectAtIndex:indexPath.row] valueForKey:@"slug"]]]; 

    if([[NSFileManager defaultManager] fileExistsAtPath:path]){ 

     listCell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:path]]; 

    } else { 

     listCell.imageView.image = [UIImage imageNamed:@"small_placeholder.gif"]; 

     NSMutableDictionary *params = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[[[listItems objectAtIndex:indexPath.row] valueForKey:@"image"] valueForKey:@"small"],@"image",[NSString stringWithFormat:@"%@_small.gif",[[listItems objectAtIndex:indexPath.row] valueForKey:@"slug"]], @"name",indexPath,@"index",@"listFileComplete",@"notification",nil]; 

     [NSThread detachNewThreadSelector:@selector(loadImages:) toTarget:self withObject:params]; 

     [params release]; 

    } 

文件donwloaded通知:

-(void)fileComplete:(NSNotification *)notification { 

    [self performSelectorOnMainThread:@selector(reloadMainThread:) withObject:[notification userInfo] waitUntilDone:NO]; 
} 

细胞重装(我已经硬编码了部分由于与陌生的部分数字的错误传递很少导致飞机坠毁:

-(void)reloadMainThread:(NSDictionary *)params { 

    NSIndexPath *index; 

    switch ([[params valueForKey:@"index"] section]) { 
     case 0: 
      index = [NSIndexPath indexPathForRow:[[params valueForKey:@"index"] row] inSection:0]; 
      [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[params valueForKey:@"index"], nil] withRowAnimation:UITableViewRowAnimationNone]; 
      break; 
     default: 
      index = [NSIndexPath indexPathForRow:[[params valueForKey:@"index"] row] inSection:2]; 
      [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:index,nil] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 

} 

回答

2

编辑:我原来的答案可能并不都集中在核心问题

在拨打reloadRows...之前,您是否正在更改行数? reloadRows...是专门制作动画的值变化,所以你的代码应该是这个样子:

UICell *cell = [self cellForRowAtIndexPath:indexPath]; 
cell.label.text = @"Something new"; 
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]]; 

是或多或少你的样子,但tableview中被遗忘的地方是什么?


前面的讨论

你不要四处打电话重载-beginUpdates-endUpdates。您可以拨打-beginUpdates-endUpdates围绕您对支持数据的相关修改,在此期间您应该致电-insertRowsAtIndexPaths:withRowAnimation:及其亲属。如果您调用更新例程,则不需要调用重载例程。在更新中重新加载是未定义的行为。

有关何时使用-beginUpdates的详细信息,请参阅Batch Insertion, Deletion, and Reloading of Rows and Sections

+0

感谢您的提示,我想我的问题是与reloadRowsAtIndexPaths和不beginUpdates因为问题仍然存在与开始/结束删除 – Alex 2011-05-24 14:50:26

+0

编辑;我可能误解了其他代码的外观。 – 2011-05-24 14:57:24

+0

我已经更新了我的问题,以便更深入地了解我的问题 – Alex 2011-05-24 15:11:49

0

你有没有试过如下:

CGPoint offset = [self.tableView contentOffset]; 
CGSize size = [self.tableView contentSize]; 

CGFloat percentScrolled = offset.y/size.height; 

// call reloadRowsAtIndexPaths, inserts, deletes etc. 
// ... 

CGSize newSize = [self.tableView contentSize]; 
CGSize newOffset = CGPointMake(0, newSize.height * percentScrolled); 

[self.tableView setContentOffset:newOffset animated:NO]; 

这似乎有点过于琐碎,不知道它会工作,但值得一试。

+0

如果它不停止滚动tableView – Alex 2011-05-24 16:36:41

0

更换

[_tableView reloadData]; 

[_tableView reloadRowsAtIndexPaths:...withRowAnimation:...]; 

,这将是很好的。

3

由于错误估计的行高,声音就像您遇到了这个问题。因为(出于某种神秘的原因)表格视图确定了使用估计行高重新加载某些单元格后的新偏移量,您要确保tableView:estimatedHeightForRowAtIndexPath为已经渲染的单元格返回正确的数据。要做到这一点,你可以缓存看出行高在词典:

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    heightForIndexPath[indexPath] = cell.frame.height 
} 

然后用这个正确的数据或您的估计尚未加载细胞:

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
    return heightForIndexPath[indexPath] ?? averageRowHeight 
} 

(非常非常感谢eyuelt的洞察力该估计的行高被用来确定新的偏移量)

+0

Wowowowow!最佳答案,我希望我可以upvote它10倍!非常感谢,丹尼尔,我希望在未来,你会发现我的答案是有用的,因为我发现你的现在 – ingaham 2016-08-10 15:37:44

+0

Wowwwwwwwwwwwwwww ....我搜索高和低的解决方案,我的问题重叠单元格和这个答案APPEARS已经解决了它。 非常爱,丹尼尔! – 2018-02-13 18:08:36

0

我使用此:

-(void)keepTableviewContentOffSetCell:(cellClass *)cell{ 
    CGRect rect = cell.frame; 
    self.tableView.estimatedRowHeight = rect.size.height ; 
} 

重新加载单元格之前,可以使用它。重新加载单元格时,表格视图不会滚动。