iOS列表UITableView性能优化之cell绘制

我的iOS王者之路 2019-06-28

  • 序言
    在我们开发工作日常中经常会遇见用UITableView处理列表页面,自定义cell也是常用方式。在整个列表优化不同方案中今天就从通常初级的自定义cell视图换成cell的绘制这一角度来进行演示和讲解。
  • 前提条件 -- iOS的绘制机制
    iOS中所有的view绘图工作均在 drawRect 方法中完成,cell当然也不例外。一般情况下只会绘制一次。如果我们想自己绘制view的内容,那么需要重写drawRect方法,而且苹果不建议直接调用此方法,如果需要的话 调用setNeedsDisplay方法会自动调用drawRect方法,也就是重新绘制一次视图。
  • 用绘制视图的方法代替用控件堆起来的自定义视图,视图加载速度会快数10倍甚至100倍。
    下面我们来看代码:
    iOS列表UITableView性能优化之cell绘制iOS列表UITableView性能优化之cell绘制

    这是自定义cell的UI代码,用masonry进行布局约束。计算出了cell加载前和加载后的时间差且打印。下面来看下打印信息:

    第 0 行cell加载消耗 0.012509 秒
    第 1 行cell加载消耗 0.001275 秒
    第 2 行cell加载消耗 0.000981 秒
    第 3 行cell加载消耗 0.000905 秒
    第 4 行cell加载消耗 0.000892 秒
    第 5 行cell加载消耗 0.000891 秒
    第 6 行cell加载消耗 0.000888 秒
    第 7 行cell加载消耗 0.000903 秒
    第 8 行cell加载消耗 0.000895 秒
    第 9 行cell加载消耗 0.000888 秒

打印信息可以看出加载这种简单样式cell时间消耗还是挺快的,平均0.00几秒。那么我们来看下cell绘制的方式来展现界面视图的方式效果如何。下面是重写celldrawRect方法,把cell中的三部分进行绘制:

- (void)drawRect:(CGRect)rect {

// 头像
CGRect  imageViewRect  = CGRectMake(15, 15, 30, 30);
UIImage *iconImage  = [UIImage imageNamed:@"images"];
[iconImage drawInRect:imageViewRect];

// 姓名
CGFloat fontSize = 16;
NSString *name = @"大白";
CGFloat width = rect.size.width - 60;
UIFont *nameFont = [UIFont boldSystemFontOfSize:fontSize];
NSDictionary *attrs = @{NSFontAttributeName : nameFont};

[name drawInRect:CGRectMake(60, 8, width, 20) withAttributes:attrs];

// 内容
NSString *content = @"这是大白想说的话";
[content drawInRect:CGRectMake(60, 35, width, 20) withAttributes:attrs];

}

达到同样的效果来看下运行时间打印:

2018-08-25 11:50:56.985876+0800 列表性能优化方案[1549:82858] 第 0 行cell加载消耗 0.000415 秒
2018-08-25 11:50:56.991175+0800 列表性能优化方案[1549:82858] 第 1 行cell加载消耗 0.000167 秒
2018-08-25 11:50:56.991874+0800 列表性能优化方案[1549:82858] 第 2 行cell加载消耗 0.000066 秒
2018-08-25 11:50:56.992405+0800 列表性能优化方案[1549:82858] 第 3 行cell加载消耗 0.000066 秒
2018-08-25 11:50:56.992927+0800 列表性能优化方案[1549:82858] 第 4 行cell加载消耗 0.000065 秒
2018-08-25 11:50:56.993470+0800 列表性能优化方案[1549:82858] 第 5 行cell加载消耗 0.000086 秒
2018-08-25 11:50:56.994018+0800 列表性能优化方案[1549:82858] 第 6 行cell加载消耗 0.000084 秒
2018-08-25 11:50:56.994520+0800 列表性能优化方案[1549:82858] 第 7 行cell加载消耗 0.000062 秒
2018-08-25 11:50:56.995033+0800 列表性能优化方案[1549:82858] 第 8 行cell加载消耗 0.000068 秒
2018-08-25 11:50:56.995558+0800 列表性能优化方案[1549:82858] 第 9 行cell加载消耗 0.000080 秒

可以看出,用绘制方式要比一般的自定义视图方式平均快了两个小数点级别。而且这还是在drawRect方法内容代码没有进行任何优化的情况下、这只是简单的cell元素个数比较少的情况下。如果碰见复杂视图的话,这种对比应该更明显。

从代码维护角度来看,代码会比较难维护,但是一旦界面稳定下来的情况下就可以用绘制方式代替复合视图。

  • 最后欢迎大家指出不足之处,希望能够交流共同进步~~

相关推荐