tableView优化
- 最基本,cell的重用。
- 固定行高的用
self.tableView.rowHeight = 40;
,而不用- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
。原因在于前者一次性固定所有 cell 高度,而后者需要每次调用绘制。 - 图片加载用异步,用
SDWebImage
,或者不在滑动过程中下载图片,在滑动过程中使用默认图片,滑动停止再下载。
代码:// Only load cached images; defer new downloads until scrolling ends if (!appRecord.appIcon) { if (self.tableView.dragging == NO && self.tableView.decelerating == NO) { [self startIconDownload:appRecord forIndexPath:indexPath]; } // if a download is deferred or in progress, return a placeholder image cell.imageView.image = [UIImage imageNamed:@"Placeholder.png"]; } else { cell.imageView.image = appRecord.appIcon; }
- 尽量减少
cell
中控件,不要使用add
和remove
添加和移除视图,而是初始化的时候添加,使用hide
隐藏。 - 当
cell
中控件过多时,在drawRect
方法中异步绘制。 - 少用或者不用透明视图。
- 尽量不动态计算行高,如果行高不固定且复杂需要计算的时候,iOS8之前我们使用
UITableView-FDTemplateLayoutCell
这个第三方框架来帮我们计算。iOS8以后使用系统方法。如下:self.tableView.estimatedRowHeight = 44; // 设置估算高度 self.tableView.rowHeight = UITableViewAutomaticDimension; // 告诉tableView我们cell的高度是自动的
- 使用字典缓存动态行高。
代码:- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { NSNumber *height = [self.heightAtIndexPath objectForKey:indexPath]; if(height) { return height.floatValue; } else { return 100; } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return UITableViewAutomaticDimension; } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { NSNumber *height = @(cell.frame.size.height); [self.heightAtIndexPath setObject:height forKey:indexPath]; }
- 尽量只定义一种 cell。如果复用 n次,m个 cell 可能会复用 m*n 次。
- 不要把计算放在
cellForRow
方法中。例如 cell 的高度,cell 所计划展示的文案,都放在 model 中。显得稍微有些不合理,如果是 MVVM 模式,放在 viewModel 中则十分合理。
在 viewModel 创建好时就计算好相关需要展示的属性,高度等,而不是在加载 tableview 时,可以以此优化。@interface DataEntity : NSObject //原始数据 @property(copy, nonatomic) NSString *content; @property(copy, nonatomic) NSString *title; //Cell 高度 @property(assign, nonatomic) CGFloat cellHeight; //真正显示的内容 @property(strong, nonatomic) NSAttributedString *showTitle; @property(strong, nonatomic) NSAttributedString *showContent; //计算高度 - (void)calculateCellHeight; //创建、加工真正显示的内容 - (void)setupShowTitileAndContent; @end
- 滑动 UITableView 时,按需加载对应的内容
代码:
记得在tableView:cellForRowAtIndexPath:方法中加入判断://按需加载 - 如果目标行与当前行相差超过指定行数,只在目标滚动范围的前后指定3行加载。 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{ NSIndexPath *ip = [self indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)]; NSIndexPath *cip = [[self indexPathsForVisibleRows] firstObject]; NSInteger skipCount = 8; if (labs(cip.row-ip.row)>skipCount) { NSArray *temp = [self indexPathsForRowsInRect:CGRectMake(0, targetContentOffset->y, self.width, self.height)]; NSMutableArray *arr = [NSMutableArray arrayWithArray:temp]; if (velocity.y<0) { NSIndexPath *indexPath = [temp lastObject]; if (indexPath.row+3<datas.count) { [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+1 inSection:0]]; [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+2 inSection:0]]; [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+3 inSection:0]]; } } else { NSIndexPath *indexPath = [temp firstObject]; if (indexPath.row>3) { [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-3 inSection:0]]; [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-2 inSection:0]]; [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-1 inSection:0]]; } } [needLoadArr addObjectsFromArray:arr]; } }
//如果当前cell不在目标前后三行内,不必须加载,调用[cell clear] 清空 if (needLoadArr.count>0&&[needLoadArr indexOfObject:indexPath]==NSNotFound) { [cell clear]; return; }
- 不要在滚动视图使用
cornerRadius
。
当图片内容不变时,圆角阴影等可以用以下代码优化:
其他方法:使用圆角图片。预处理圆角图片。单色背景下加入镂空圆形图片。//开启shouldRasterize后,CALayer会被光栅化为bitmap,layer的阴影等效果也会被保存到bitmap中复用。 self.layer.shouldRasterize = YES; self.layer.rasterizationScale = [UIScreen mainScreen].scale;
网友评论