滚动时 TableView 单元格很慢
Posted
技术标签:
【中文标题】滚动时 TableView 单元格很慢【英文标题】:TableView cells are being slow when scrolling 【发布时间】:2013-07-15 22:47:06 【问题描述】:我有一个显示 Facebook 好友列表的 tableView。我在单元格中有一个图像视图,它显示用户的 profilePicture。使用 AFNetworking 我调用新图像并在加载时放置一个占位符。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"FbFriendCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// Configure the cell...
if (tableView == self.searchDisplayController.searchResultsTableView)
NSDictionary *friend = (NSDictionary *)[self.searchResults objectAtIndex:indexPath.row];
cell.textLabel.text = [friend valueForKey:@"name"];
else
NSDictionary *friend = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
UIImageView *profilePic = (UIImageView *)[cell.contentView viewWithTag:10];
UILabel *displayName = (UILabel *)[cell.contentView viewWithTag:20];
UIButton *playButton = (UIButton *)[cell.contentView viewWithTag:30];
displayName.text = [friend valueForKey:@"name"];
UIImage *defaultPhoto = [UIImage imageNamed:@"person.png"];
NSString *urlString = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture", friend[@"id"]];
NSURL *avatarUrl = [NSURL URLWithString:urlString];
[profilePic setImageWithURL:avatarUrl placeholderImage:defaultPhoto];
profilePic.contentMode = UIViewContentModeScaleAspectFit;
这会导致 tableview 出现一些速度/性能问题。有谁知道为什么会这样,这个设置正确吗?
单元格是使用情节提要创建的原型单元格。我还有其他代码用于单元格中的其他对象,但删除配置文件图片部分会使单元格正常执行,所以这似乎是问题所在,只是不知道为什么。
编辑
UIImage *defaultPhoto = [UIImage imageNamed:@"person40x40.png"];
NSString *urlString = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?width=40&height=40", friend[@"id"]];
我已更新图片以适应 40x40 图像视图,但没有区别。 iphone4 加载表格单元格的速度很慢。相比iphone5滚动非常流畅。
这是 Time Profiler 中最重的:
看起来 profilePic 是最差的。这是因为来自 Facebook 的数据请求。我已将 profilePic 更改为仅不是 URL 请求的默认 Pic,并且表格视图很好。所以这显然是 setImageWithURL 的性能问题。
看看其他问题,这似乎是实现这一目标的最佳方式:- Best practices for managing facebook friends pics in ios App
欢迎讨论
【问题讨论】:
头像有多大? 如果删除 profilePic 会怎样?是不是更快? 它可能会有所帮助,setImageWithURL: 来自 AFNetworking 库,它正在异步加载图像:engineering.gowalla.com/AFNetworking/Categories/…: @PatrickTescher checkout graph.facebook.com/martin-magakian/picture 请求的图片很小 @MartinMagakian 如果你想使用它 Facebook 有自己的头像查看类:developers.facebook.com/docs/reference/ios/3.5/class/… 它会自动选择合适的图片下载,管理 url 连接等。 【参考方案1】:自动布局可能会导致一些问题。此外,如果您在图像进入时调整它们的大小,这可能会导致速度变慢。确定最简单的方法是运行 Time Profiler(选中 Hide System Libraries 和 Show Obj-C Only)。这会告诉你你的缓慢来自哪里。
【讨论】:
Hide System Libraries
提示在查看时间分析器时非常有用。【参考方案2】:
我现在几乎没有什么想法可以改善您的性能问题。
1) 请求您的朋友改进
从您的编辑看来,请求您的朋友也需要相当长的时间:
NSDictionary *friend = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
我相信您可以使用以下内容缓存大部分调用:
-(void)viewDidLoad
[super viewDidLoad];
this.friendsInsensitive = [self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
2) Web 请求改进 1/2 阅读一些关于NSURLConnection and the event loop 和blocking the main thread with async call 的帖子
让我们尝试一下。在另一个线程中调用图像 Web 请求。
[...]
UIImageView *profilePic = (UIImageView *)[cell.contentView viewWithTag:10];
UILabel *displayName = (UILabel *)[cell.contentView viewWithTag:20];
UIButton *playButton = (UIButton *)[cell.contentView viewWithTag:30];
displayName.text = [friend valueForKey:@"name"];
UpdateImgContainter *containter = [UpdateImgContainter alloc] initWithCell:cell andFriendId:friend[@"id"];
[self performSelectorInBackground:@selector(requestImg:) withObject:containter];
-(void)requestImg:(UpdateImgContainter *)containter
UIImage *defaultPhoto = [UIImage imageNamed:@"person.png"];
NSString *urlString = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture", containter.friendId];
NSURL *avatarUrl = [NSURL URLWithString:urlString];
[profilePic setImageWithURL:avatarUrl placeholderImage:defaultPhoto]; //warning it's not good practice to upload the UI from an other thread than MainThread
profilePic.contentMode = UIViewContentModeScaleAspectFit;
2) Web 请求改进 2/2 我只是找到了另一种方法来做到这一点。而且它可能更可靠。 从 Apple 本身下载此 LazyTableImages project。它的创建正是为了教授您面临的问题。 归根结底,我只是认为 setImageWithURL: 可能没有那么快(?),并且点 N°1 也可能是您问题的一部分。查看LazyTableImages project Apple 只需使用 NSURLConnection。
【讨论】:
以上是关于滚动时 TableView 单元格很慢的主要内容,如果未能解决你的问题,请参考以下文章
限制tableView中显示的单元格数量,滚动到最后一个单元格时加载更多单元格