当我在asynchronous重载数据期间滚动时,为什么我的UITableView失去stream动性?

这是我的问题…我正在对我正在使用的服务进行asynchronous调用,它将search结果返回给我。 完成后,重新载入我的表,并完成asynchronous。 问题是,当我尝试在asynchronous调用完成之前在我的表视图上滚动时,该表失去了所有滚动视图所具有的stream畅感。 我的意思是,当你放开卷轴而不是继续前进,慢慢停下来的时候,只要你放开,它就会停下来。 唯一的方法来恢复stream体的感觉是滚动一直到UITableView的顶部或底部和一点点过去,那就没事了。

这是我的asynchronous调用代码:

__block NSMutableArray *appendMoreObjects = [[NSMutableArray alloc] init]; dispatch_async( dispatch_get_main_queue(), ^{ self.activity.hidden = NO; appendMoreObjects = [service search:self.query from:((moreCount * 8)) until:((moreCount * 8) + 8)]; if( appendMoreObjects == nil ) { //alert view } else { [self.allSearchResults addObjectsFromArray:appendMoreObjects]; [self updateSearchArray]; self.moreCount += 1; } self.activity.hidden = YES; }); 

另外,请记住,我正在使用自定义的UITableViewCell。 如果需要其他信息,请申请,我会看看我能做些什么。 先谢谢你。

EDIT1:[self updateSearchArray]包含[tableView reloadData]

编辑2:我在运行4.3.1(8G4)的iPod Touch上testing

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { customCell * cell = (customCell *)[tableView dequeueReusableCellWithIdentifier:@"cell"]; if( cell == nil ) { cell = [[[customCell alloc] initWithFrame:CGRectZero] autorelease]; } if( indexPath.row == [self.searchResults count] && [self.searchResults count] > 0) { UITableViewCell *moreCell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease]; moreCell.textLabel.text = @"More"; moreCell.textLabel.textAlignment = UITextAlignmentCenter; return moreCell; } if( indexPath.row < [self.searchResults count] ) { [cell formatAndInsertData:[self.searchResults objectAtIndex:indexPath.row]]; } return cell; } 

解:

我最终做的是locking桌子和所有的用户界面元素,直到调用完成。 也许不是最好的解决scheme,但它的工作就不那么简单了。

调用[tableView reloadData]将重新加载你的ENTIRE表,这就是你看到波涛汹涌的UITableView的原因。 它强制所有可见的单元格刷新,因此,当您滚动时,可见单元格会刷新并重新绘制自己。 您需要重新评估更新UITableView的策略,因为您有数据来避免这种情况。 您应该更新单个单元格,这些单元格可能包含与您的更新相关的数据。

为此,您将需要使用以下方法:

 – insertRowsAtIndexPaths:withRowAnimation: – deleteRowsAtIndexPaths:withRowAnimation: – reloadRowsAtIndexPaths:withRowAnimation: 

这些组合将允许您在接收数据时更新您的表(添加/删除行),而不是强制刷新整个表。

确保你只是在主线程上重新加载表数据。 最好,我使用nsinvocation而不是GCD 🙂

我想看看自定义单元格,以完全回答你的问题。

此外,您的表格控制器cellForRowAtIndexPath:段,看看你是如何重用您的单元格。

最后但并非最不重要的是:您正在testing哪种types的设备? (types和世代)

编辑:

这部分 :

 if( indexPath.row == [self.searchResults count] && [self.searchResults count] > 0) { UITableViewCell *moreCell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease]; moreCell.textLabel.text = @"More"; moreCell.textLabel.textAlignment = UITextAlignmentCenter; return moreCell; } 

看起来彻头彻尾的有毒…现在没有时间来testing它,但请不要在单元格内添加单元格… tablecontroller将不仅困惑,但阻止了太多的内存。

只使用cellForRowAtIndexPath:简单的事情,如填写标题,描述和图像。

在桌面视图控制器上执行重新加载逻辑,但在某处更安全。 cellForRowAtIndexPath将在每次出现单元格时加载,即使它正好在视线内。