iOS TableView性能优化

果子爸聊技术 2017-12-20 17:12:23 ⋅ 71 阅读


TableView的性能优化非常考验开发的基本功,之前做项目实战的时候经常被这个问题困扰,在实战过程中通过性能工具、查阅文档和不断的整理思路,解决方案如下:

1. 对象创建;

1.1 TableView初始化

#pragma 懒加载
- (UITableView *)tableView{
    if (!_tableView) {
        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - self.cycleScrollView2.frame.size.height)];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        [self.view addSubview:_tableView];
    }
    return _tableView;
}

1.2 复用cell

从 iOS 6 以后,我们在 UITableView 和 UICollectionView 中可以复用 Cell以及各个 Section 的 Header 和 Footer。

确保TableviewCell/Header/Footer使用了复用机制, 而不是每一次都创建;

@interface HomeVC ()<UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) UITableView *tableView;

@end

static NSString *cellId = @"Cell";

@implementation HomeVC

- (void)viewDidLoad {
    [super viewDidLoad];

    self.myTableView.delegate = self;
    self.myTableView.dataSource = self;
//第一种注册cell<nib文件类HomeTableViewCell>
    [self.tableView registerNib:[UINib nibWithNibName:@"HomeTableViewCell" bundle:nil] forCellReuseIdentifier:cellId];

//第二种注册Cell<纯手工打造的HomeVC>
// [self.tableView registerClass:[HomeVC class]forCellReuseIdentifier:cellId];

}

#pragma 代理

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    //获取重用池中的cell
    HomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    //如果没有取到,就初始化
    if (!cell) {
        cell = [[HomeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
    }

    cell.cellNameLab.text = @"Name";
    return cell;
}
1.2.1 以下为重用相关API
// 复用 Cell:
- [UITableView dequeueReusableCellWithIdentifier:];
- [UITableView registerNib:forCellReuseIdentifier:];
- [UITableView registerClass:forCellReuseIdentifier:];
- [UITableView dequeueReusableCellWithIdentifier:forIndexPath:];
// 复用 Section 的 Header/Footer:
- [UITableView registerNib:forHeaderFooterViewReuseIdentifier:];
- [UITableView registerClass:forHeaderFooterViewReuseIdentifier:];
- [UITableView dequeueReusableHeaderFooterViewWithIdentifier:];

2. TabelView 代理

2.1 避免快速滑动情况下开过多线程。

cell中的图片开线程异步加载SDWebImage(异步操作)。但是线程开过多了会造成资源浪费,内存开销过大。图片过多时可以不要一滚动就走cellForRow方法,可以在scrollview的代理方法中做限制,当滚动开始减速的时候才加载显示在当前屏幕上的cell(通过tableview的dragging和declearating两个状态也能判断)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    //如果没有取到,就初始化
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    }
    cell.textLabel.text = @"Name";

    BOOL canLoad = !self.tableView.dragging && !_tableView.decelerating;
    if  (canLoad) {
        //开始loaddata,异步加载图片
        NSLog(@"开始加载图片");
    }
    return cell;
}

// 滚动停止时,触发该函数
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    //刷新tableview
   // [self.tableView reloadData];

 //在此刷新的是屏幕上显示的cell的内容
    NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
    //获取到的indexpath为屏幕上的cell的indexpath
    [self.tableView reloadRowsAtIndexPaths:visiblePaths withRowAnimation:UITableViewRowAnimationRight];

}

3. 图片圆角

3.1 layer.cornerRadius

imageView.layer.cornerRadius = imageView.frame.size.width/2.0;  
// 隐藏边界
imageView.layer.masksToBounds = YES;

3.2 头像使用蒙版+贝塞尔曲线加圆角

CAShapeLayer *layer = [[CAShapeLayer alloc] init];

UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.icon.width / 2, self.icon.height / 2) radius:self.icon.width / 2  startAngle:0 endAngle:M_PI * 2 clockwise:YES];

layer.path = path.CGPath;
self.icon.layer.mask = layer;

3.3 stackoverflow

UIImageView *iconImage = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    [self.view addSubview:iconImage];

    // Get your image somehow
    UIImage *image = [UIImage imageNamed:@"image.jpg"];
    // Begin a new image that will be the new image with the rounded corners
    // (here with the size of an UIImageView)
    UIGraphicsBeginImageContextWithOptions(iconImage.bounds.size, NO, [UIScreen mainScreen].scale);
    // Add a clip before drawing anything, in the shape of an rounded rect
    [[UIBezierPath bezierPathWithRoundedRect:iconImage.bounds cornerRadius:10.0] addClip];
    // Draw your image
    [image drawInRect:iconImage.bounds];
    // Get the image, here setting the UIImageView image
    iconImage.image = UIGraphicsGetImageFromCurrentImageContext();
    // Lets forget about that we were drawing
    UIGraphicsEndImageContext();

4. 异步加载图片

第一种方法: SDWebImage的使用

[imageView sd_setImageWithURL:url completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
            imageView.image = image;
}];

5 优化UITableViewCell高度计算

Tip
1. 使用不透明视图, 如非必要, 可以设置opaque为yes;
2. 图片的alpha尽量不设置透明度;
3. cellForRowAtIndexPath不要做耗时操作, 
   * 读取文件/写入文件;
   * 尽量不要去添加和移除view;

请继续关注“IT实战联盟”哦~~~




全部评论: 0

    我有话说:

    移动H5前端五大性能优化方案(实战篇)

    移动H5前端五大性能优化方案(实战篇)

    抖音品质建设 - iOS启动优化《原理篇》

    前言 启动是 App 给用户的第一印象,启动越慢用户流失的概率就越高,良好的启动速度是用户体验不可缺少的一环。启动优化涉及到的知识点非常多面也很广,一篇文章难以包含全部,所以拆分成两部分:原理和实践

    前端性能分析工具-Keepfast

    能够分析网站的资源构建性能和页面性能,生成性能报告并提供优化建议,让性能监控更方便。

    iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+

    iOS OOM 崩溃在生产环境中的归因一直是困扰业界已久的疑难问题,字节跳动旗下的头条、抖音等产品也面临同样的问题。在字节跳动性能与稳定性保障团队的研发实践中,我们自研了一款基于内存快照技术并且可

    iOS实战篇:iOS 界面卡顿原因

    界面卡顿的原因在 VSync[1] 信号到来后,系统图形服务会通过 CADisplayLink 等机制通知 App,App 主线程开始在 CPU 中计算显示内容......

    Netty单机百万连接及高性能优化

    关于netty的学习和介绍,可以去github看官方文档,这里良心推荐《netty实战》和《netty权威指南》两本书,前者对于新手更友好,原理和应用都有讲到,多读读会发现很多高性能的优化点。

    iOS直播---音/视频采集/压缩(二)

    不好意思,我们来晚了! 但我们不会缺席。

    iOS直播---主要的概念(一)

    直播可谓风生水起, 热火朝天, 借此也对音视频进行一次深入学习, 希望有需要的大家一块学习.第一步对直播的大

    iOS实战篇:[译]iOS扩充--OCR光学字符识别(内附项目GitHub地址)

    OCR(Optical Character Recognition) 光学字符识别, 是从图像中电子扫描提取文本的过程, 可以在文档编辑等多种形式重用它,例如: 文本搜索/压缩等用途。

    RedisPlus 3.0.0 重构归来免费开源,优化性能和交互体验

    RedisPlus是为Redis可视化管理开发的一款开源免费的桌面客户端软件,支持Windows 、Linux、Mac三大系统平台,RedisPlus提供更加高效、方便、快捷的使用体验,有着更加现代化的用户界面风格。

    抖音品质建设 - iOS启动优化《实战篇》

    前言 启动是 App 给用户的第一印象,启动越慢,用户流失的概率就越高,良好的启动速度是用户体验不可缺少的一环。启动优化涉及到的知识点非常多,面也很广,一篇文章难以包含全部,所以拆分成两部分:原理和

    今日头条 iOS 安装包大小优化 - 新阶段、新实践

    前言 今日头条 iOS 端从 2016 年起就关注到了安装包大小的问题,并启动了包大小优化。2017 年,我们将当时的经验发表为技术文章 《干货|今日头条iOS端安装包大小优化—思路与实践

    专业解决 MySQL 查询速度慢与性能

    什么影响了数据库查询速度?关于数据库性能并不是DBA才关心的事。

    Java Web实战篇:增强for循环实现原理及for循环实战性能优化

    Iterator是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator被创建之后会建立一个指向原来对象的单链索引表......

    IntelliJ IDEA 开启很慢,运行不流畅,大项目卡顿?一招配置解决!

    来源:Java面试题精选 一、前言 IDEA默认启动配置主要考虑低配置用户,参数不高(默认最低128m,最高512m),导致启动慢,然后运行也不流畅,这里我们需要优化下启动和运行配置;但是在工作中

    性能与架构」MySQL 8 查询优化新工具 Explain Analyze

    Explain 是我们常用的查询分析工具,可以对查询语句的执行方式进行评估,给出很多有用的线索。