美文网首页
iOS 性能优化:一个tableView卡顿案例实战

iOS 性能优化:一个tableView卡顿案例实战

作者: 某非著名程序员 | 来源:发表于2019-08-07 18:39 被阅读0次

  tableView是我们经常使用的控件,但界面复杂了,优化的点还是有很多的。
  1.数据量大时,高度必须缓存。无论是使用第三方还是自己写的,如果计算数据复杂可后台线程计算。
  2.相信我们平时使用tableView的时候,如果高度做了缓存,应该很少见到卡顿。下面结合实际卡顿的例子,然后介绍一些优化的方法:

@interface InstrumentsViewController ()<UITableViewDataSource,UITableViewDelegate>
@property (nonatomic, strong) NSArray *items;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end

@implementation InstrumentsViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    NSMutableArray *array = [NSMutableArray array];
    for (int i = 0; i < 1000; i++) {
        //add name
        [array addObject:@{@"name": [self randomName], @"image": [self randomAvatar]}];
    }
    self.items = array;
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //dequeue cell
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    //load image
    NSDictionary *item = self.items[indexPath.row];
    NSString *filePath = [[NSBundle mainBundle] pathForResource:item[@"image"] ofType:@"png"];
    //set image and text
    cell.imageView.image = [UIImage imageWithContentsOfFile:filePath];
    cell.textLabel.text = item[@"name"];
    //set image shadow
    cell.imageView.layer.shadowOffset = CGSizeMake(0, 5);
    cell.imageView.layer.shadowOpacity = 0.75;
    cell.clipsToBounds = YES;
    
    //set text shadow
    cell.textLabel.backgroundColor = [UIColor clearColor];
    cell.textLabel.layer.shadowOffset = CGSizeMake(0, 2);
    cell.textLabel.layer.shadowOpacity = 0.5;
    
    return cell;
}


- (NSString *)randomName
{
    NSArray *first = @[@"Alice", @"Bob", @"Bill", @"Charles", @"Dan", @"Dave", @"Ethan", @"Frank"];
    NSArray *last = @[@"Appleseed", @"Bandicoot", @"Caravan", @"Dabble", @"Ernest", @"Fortune"];
    NSUInteger index1 = (rand()/(double)INT_MAX) * [first count];
    NSUInteger index2 = (rand()/(double)INT_MAX) * [last count];
    return [NSString stringWithFormat:@"%@ %@", first[index1], last[index2]];
}

- (NSString *)randomAvatar
{
    NSArray *images = @[@"Snowman", @"Igloo", @"Cone", @"Spaceship", @"Anchor", @"Key"];
    NSUInteger index = (rand()/(double)INT_MAX) * [images count];
    return images[index];
}

  一个简单的tableView,1000个数据源,高度固定。图片加载采用imageWithContentsOfFile,因为imageName会对资源中的图片做优化。添加阴影。
  测试卡顿一定要拿真机调试,而且最好是需要兼容的性能最差的机子,我的例子是在5c上运行的。另外最好使用release版本,因为xcode在发布版本会做很多优化,至少不会打印NSLog日志。instruments 可以检测帧率。


5c快速滑动列表
5c快速滑动帧率

  可以看到在5c上最高也就20FPS左右,掉帧非常厉害。另外我在iPhone8上测试,发现能达到最高能到60fps,这也是为什么要在最差性能手机上测试的原因。
  苹果提供了一系列复选框选项来帮助调试渲染瓶颈,我仅介绍几个常用,下面是设置方法:


真机设置方法
模拟器设置方法

1.Color Blended Layers - 这个选项基于渲染程度对屏幕中的混合区域进行绿到红的高亮(也就是多个半透明图层的叠加)。由于重绘的原因,混合对GPU性能会有影响,同时也是滑动或者动画帧率下降的罪魁祸首之一。
2.ColorHitsGreenandMissesRed - 当使用 shouldRasterizep 属性的时候,耗时的图层绘制会被缓存,然后当做一个简单的扁平图片呈现。当缓存再生的时候这个选项就用红色对栅格化图层进行了高亮。如果缓存频繁再生的话,就意味着栅格化可能会有负面的性能影响了(更多关于使用 shouldRasterize 的细节见第15章“图层性能”)。大部分都是绿色,只有当滑动到屏幕上的时候会闪烁成红色。
3.Color Copied Images - 有时候寄宿图片的生成意味着Core Animation被强制生成一些图片,然后发送到渲染服务器,而不是简单的指向原始指针。这个选项把这些图片渲染成蓝色。复制图片对内存和CPU使用来说都是一项非常昂贵的操作,所以应该尽可能的避免。
4.Color Offscreen-Rendered Yellow - 这里会把那些需要离屏渲染的图层高亮成黄色。这些图层很可能需要用 shadowPath 或者 shouldRasterize 来优化.

我们先看下Color Offscreen-Rendered Yellow 选项:


离屏渲染高亮成黄色

  由于设置了阴影,整个tableView都是黄色的。可以关掉阴影来验证下。


禁止阴影
  发现禁止阴影后离屏渲染就消失了,这个时候可以再测下帧率。 禁止阴影后的帧率

  由此可以看出,造成性能的瓶颈是阴影造成的离屏渲染。但阴影的效果我们还是需要的,这里可以是shouldRasterize来优化。shouldRasterize:可以提供很大的性能优势,但是一定要避免作用在内容不断变动的图层上,否则它缓存方面的好处就会消失,而且会让性能变的更糟。
  设置shouldRasterize后的离屏渲染还在,但由于有了缓存,界面能保持流畅。

总结:
1.性能优化的方面有很多,比如可以给图片使用时添加缓存,可以使用CATiledLayer来替代view的展示,减少透明图层的使用,对于不需要不断变动时可以采用光栅化,加载图片时可以延迟解压,使用图层内容等方式。
2.文中内容只是抛砖引玉,更多内容可阅读<<iOS CoreAnimation>>书籍。
3.demo包含<<iOS CoreAnimation>>整本书的例子,可方便观看。

相关文章

网友评论

      本文标题:iOS 性能优化:一个tableView卡顿案例实战

      本文链接:https://www.haomeiwen.com/subject/sviedctx.html